From 97d385648b3b9a17e9c8c1cddc2d1c911e93d382 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Wed, 13 Jan 2016 16:10:04 +0900 Subject: [PATCH] Replace PHPMailer with SwiftMailer (via Mail class from Advanced Mailer) --- classes/mail/Mail.class.php | 696 ++--- libs/phpmailer/LICENSE | 504 ---- libs/phpmailer/class.phpmailer.php | 1909 -------------- libs/phpmailer/class.smtp.php | 1062 -------- libs/phpmailer/index.html | 1 - libs/phpmailer/language/index.html | 1 - libs/phpmailer/language/phpmailer.lang-en.php | 23 - libs/phpmailer/phpmailer.php | 2320 ----------------- libs/phpmailer/smtp.php | 815 ------ 9 files changed, 261 insertions(+), 7070 deletions(-) delete mode 100644 libs/phpmailer/LICENSE delete mode 100644 libs/phpmailer/class.phpmailer.php delete mode 100644 libs/phpmailer/class.smtp.php delete mode 100644 libs/phpmailer/index.html delete mode 100644 libs/phpmailer/language/index.html delete mode 100644 libs/phpmailer/language/phpmailer.lang-en.php delete mode 100644 libs/phpmailer/phpmailer.php delete mode 100644 libs/phpmailer/smtp.php diff --git a/classes/mail/Mail.class.php b/classes/mail/Mail.class.php index 14b58ccf4..3877adaba 100644 --- a/classes/mail/Mail.class.php +++ b/classes/mail/Mail.class.php @@ -1,165 +1,53 @@ */ - -require_once _XE_PATH_ . "libs/phpmailer/phpmailer.php"; /** - * Mailing class for XpressEngine - * - * @author NAVER (developers@xpressengine.com) + * Mail class + * + * This class was originally written for the Advanced Mailer module. + * Advanced Mailer is licensed under GPLv2, but the author hereby relicenses + * this class under the same license as the remainder of RhymiX. + * All other parts of the Advanced Mailer module remain under GPLv2. + * + * @author Kijin Sung */ -class Mail extends PHPMailer +class Mail { - /** - * Sender name - * @var string + * Properties for compatibility with XE Mail class */ - var $sender_name = ''; - + public $content = ''; + public $content_type = 'html'; + public $attachments = array(); + public $cidAttachments = array(); + /** - * Sender email address - * @var string + * Properties used by Advanced Mailer */ - var $sender_email = ''; - + public $error = null; + public $caller = null; + public $message = null; + public static $transport = null; + /** - * Receiptor name - * @var string + * Constructor */ - var $receiptor_name = ''; - - /** - * Receiptor email address - * @var string - */ - var $receiptor_email = ''; - - /** - * Title of email - * @var string - */ - var $title = ''; - - /** - * Content of email - * @var string - */ - var $content = ''; - - /** - * Content type - * @var string - */ - var $content_type = 'html'; - - /** - * Message id - * @var string - */ - var $messageId = NULL; - - /** - * Reply to - * @var string - */ - var $replyTo = NULL; - - /** - * BCC (Blind carbon copy) - * @var string - */ - var $bcc = NULL; - - /** - * Attachments - * @var array - */ - var $attachments = array(); - - /** - * Content attachements - * @var array - */ - var $cidAttachments = array(); - - /** - * ??? - * @var ??? - */ - var $mainMailPart = NULL; - - /** - * Raw body - * @var string - */ - var $body = ''; - - /** - * Raw header - * @var string - */ - var $header = ''; - - /** - * End of line - * @var string - */ - var $eol = ''; - - /** - * Reference - * @var string - */ - var $references = ''; - - /** - * Additional parameters - * @var string - */ - var $additional_params = NULL; - - /** - * Whether use or not use stmp - * @var bool - */ - var $use_smtp = FALSE; - - /** - * Constructor function - * - * @return void - */ - function __construct() + public function __construct() { - + $this->message = \Swift_Message::newInstance(); } - + /** * Set parameters for using Gmail * - * @param string $account_name Password - * @param string $account_passwd Secure method ('ssl','tls') + * @param string $account_name Email address + * @param string $account_passwd Email password * @return void */ - function useGmailAccount($account_name, $account_passwd) + public static function useGmailAccount($account_name, $account_passwd) { - $this->SMTPAuth = TRUE; - $this->SMTPSecure = "tls"; - $this->Host = 'smtp.gmail.com'; - $this->Port = '587'; - if($this->isVaildMailAddress($account_name)) - { - $this->Username = $account_name; - } - else - { - $this->Username = $account_name . '@gmail.com'; - } - $this->Password = $account_passwd; - $this->IsSMTP(); + self::useSMTP(null, 'smtp.gmail.com', $account_name, $account_passwd, 'ssl', 465); } - + /** * Set parameters for using SMTP protocol * @@ -172,67 +60,26 @@ class Mail extends PHPMailer * * @return bool TRUE if SMTP is set correct, otherwise return FALSE */ - function useSMTP($auth = NULL, $host = NULL, $user = NULL, $pass = NULL, $secure = NULL, $port = 25) + public static function useSMTP($auth = null, $host = null, $user = null, $pass = null, $secure = null, $port = 25) { - $this->SMTPAuth = $auth; - $this->Host = $host; - $this->Username = $user; - $this->Password = $pass; - $this->Port = $port; - - if($secure == 'ssl' || $secure == 'tls') + self::$transport = \Swift_SmtpTransport::newInstance($host, $port, $secure); + self::$transport->setUsername($user); + self::$transport->setPassword($pass); + $local_domain = self::$transport->getLocalDomain(); + if (preg_match('/^\*\.(.+)$/', $local_domain, $matches)) { - $this->SMTPSecure = $secure; - } - - if(($this->SMTPAuth !== NULL && $this->Host !== NULL && $this->Username !== NULL && $this->Password !== NULL) || ($this->SMTPAuth === NULL && $this->Host !== NULL)) - { - $this->IsSMTP(); - $this->AltBody = "To view the message, please use an HTML compatible email viewer!"; - return TRUE; - } - else - { - $this->IsMail(); - return FALSE; + self::$transport->setLocalDomain($matches[1]); } } - + /** * Set additional parameters - * - * @param string $additional_params Additional parameters - * @return void */ - function setAdditionalParams($additional_params) + public function setAdditionalParams($additional_params) { - $this->additional_params = $additional_params; + // no-op } - - /** - * Add file attachment - * - * @param string $filename File name to attach - * @param string $orgfilename Real path of file to attach - * @return void - */ - function addAttachment($filename, $orgfilename) - { - $this->attachments[$orgfilename] = $filename; - } - - /** - * Add content attachment - * - * @param string $filename Real path of file to attach - * @param string $cid Content-CID - * @return void - */ - function addCidAttachment($filename, $cid) - { - $this->cidAttachments[$cid] = $filename; - } - + /** * Set Sender (From:) * @@ -240,172 +87,246 @@ class Mail extends PHPMailer * @param string $email Sender email address * @return void */ - function setSender($name, $email) + public function setSender($name, $email) { - if($this->Mailer == "mail") + try { - $this->sender_name = $name; - $this->sender_email = $email; + $this->message->setFrom(array($email => $name)); } - else + catch (\Exception $e) { - $this->SetFrom($email, $name); + $this->errors[] = array($e->getMessage()); } } - + /** * Get Sender (From:) * * @return string */ - function getSender() + public function getSender() { - if(!stristr(PHP_OS, 'win') && $this->sender_name) + $from = $this->message->getFrom(); + foreach($from as $email => $name) { - return sprintf("%s <%s>", '=?utf-8?b?' . base64_encode($this->sender_name) . '?=', $this->sender_email); + if($name === '') + { + return $email; + } + else + { + return $name . ' <' . $email . '>'; + } } - return $this->sender_email; + return FALSE; } - + /** - * Set Receiptor (TO:) + * Set Recipient (To:) * - * @param string $name Receiptor name - * @param string $email Receiptor email address + * @param string $name Recipient name + * @param string $email Recipient email address * @return void */ - function setReceiptor($name, $email) + public function setReceiptor($name, $email) { - if($this->Mailer == "mail") + try { - $this->receiptor_name = $name; - $this->receiptor_email = $email; + $this->message->setTo(array($email => $name)); } - else + catch (\Exception $e) { - $this->AddAddress($email, $name); + $this->errors[] = array($e->getMessage()); } } - + /** - * Get Receiptor (TO:) + * Get Recipient (To:) * * @return string */ - function getReceiptor() + public function getReceiptor() { - if(!stristr(PHP_OS, 'win') && $this->receiptor_name && $this->receiptor_name != $this->receiptor_email) + $to = $this->message->getTo(); + foreach($to as $email => $name) { - return sprintf("%s <%s>", '=?utf-8?b?' . base64_encode($this->receiptor_name) . '?=', $this->receiptor_email); + if($name === '') + { + return $email; + } + else + { + return $name . ' <' . $email . '>'; + } } - return $this->receiptor_email; + return FALSE; } - + /** - * Set Email's Title + * Set Subject * - * @param string $title Title to set + * @param string $subject The subject * @return void */ - function setTitle($title) + public function setTitle($subject) { - if($this->Mailer == "mail") - { - $this->title = $title; - } - else - { - $this->Subject = $title; - } + $this->message->setSubject(strval($subject)); } - + /** - * Get Email's Title + * Get Subject * * @return string */ - function getTitle() + public function getTitle() { - return '=?utf-8?b?' . base64_encode($this->title) . '?='; + return $this->message->getSubject(); } - + /** * Set BCC * * @param string $bcc * @return void */ - function setBCC($bcc) + public function setBCC($bcc) { - if($this->Mailer == "mail") + try { - $this->bcc = $bcc; + $this->message->setBcc(array($bcc)); } - else + catch (\Exception $e) { - $this->AddBCC($bcc); + $this->errors[] = array($e->getMessage()); } } - + + /** + * Set ReplyTo + * + * @param string $replyTo + * @return void + */ + public function setReplyTo($replyTo) + { + try + { + $this->message->setReplyTo(array($replyTo)); + } + catch (\Exception $e) + { + $this->errors[] = array($e->getMessage()); + } + } + + /** + * Set Return Path + * + * @param string $returnPath + * @return void + */ + public function setReturnPath($returnPath) + { + try + { + $this->message->setReturnPath($returnPath); + } + catch (\Exception $e) + { + $this->errors[] = array($e->getMessage()); + } + } + /** * Set Message ID * * @param string $messageId * @return void */ - function setMessageID($messageId) + public function setMessageID($messageId) { - $this->messageId = $messageId; + $this->message->getHeaders()->get('Message-ID')->setId($messageId); } - + /** * Set references * * @param string $references * @return void */ - function setReferences($references) + public function setReferences($references) { - $this->references = $references; + $headers = $this->message->getHeaders(); + $headers->addTextHeader('References', $references); } - - /** - * Set ReplyTo param - * - * @param string $replyTo - * @return void - */ - function setReplyTo($replyTo) - { - if($this->Mailer == "mail") - { - $this->replyTo = $replyTo; - } - else - { - $this->AddReplyTo($replyTo); - } - } - + /** * Set message content * * @param string $content Content * @return void */ - function setContent($content) + public function setContent($content) { $content = preg_replace_callback('/]+)>/i', array($this, 'replaceResourceRealPath'), $content); - if($this->Mailer == "mail") - { - $this->content = $content; - } - else - { - $this->MsgHTML($content); - } + $this->content = $content; } - + + /** + * Set the type of message content (html or plain text) + * + * @param string $mode The type + * @return void + */ + public function setContentType($type = 'html') + { + $this->content_type = $type === 'html' ? 'html' : ''; + } + + /** + * Get the Plain content of body message + * + * @return string + */ + public function getPlainContent() + { + return chunk_split(base64_encode(str_replace(array("<", ">", "&"), array("<", ">", "&"), $this->content))); + } + + /** + * Get the HTML content of body message + * + * @return string + */ + public function getHTMLContent() + { + return chunk_split(base64_encode($this->content_type != 'html' ? nl2br($this->content) : $this->content)); + } + + /** + * Add file attachment + * + * @param string $filename File name to attach + * @param string $original_filename Real path of file to attach + * @return void + */ + public function addAttachment($filename, $original_filename) + { + $this->attachments[$original_filename] = $filename; + } + + /** + * Add content attachment + * + * @param string $original_filename Real path of file to attach + * @param string $cid Content-CID + * @return void + */ + public function addCidAttachment($original_filename, $cid) + { + $this->cidAttachments[$cid] = $original_filename; + } + /** * Replace resourse path of the files * @@ -413,188 +334,93 @@ class Mail extends PHPMailer * @param array $matches Match info. * @return string */ - function replaceResourceRealPath($matches) + public function replaceResourceRealPath($matches) { - return preg_replace('/src=(["\']?)files/i', 'src=$1' . Context::getRequestUri() . 'files', $matches[0]); + return preg_replace('/src=(["\']?)files/i', 'src=$1' . \Context::getRequestUri() . 'files', $matches[0]); } - - /** - * Get the Plain content of body message - * - * @return string - */ - function getPlainContent() - { - return chunk_split(base64_encode(str_replace(array("<", ">", "&"), array("<", ">", "&"), $this->content))); - } - - /** - * Get the HTML content of body message - * - * @return string - */ - function getHTMLContent() - { - return chunk_split(base64_encode($this->content_type != 'html' ? nl2br($this->content) : $this->content)); - } - - /** - * Set the type of body's content - * - * @param string $mode - * @return void - */ - function setContentType($mode = 'html') - { - $this->content_type = $mode == 'html' ? 'html' : ''; - } - + /** * Process the images from attachments * * @return void */ - function procAttachments() + public function procAttachments() { - if($this->Mailer == "mail") - { - if(count($this->attachments) > 0) - { - $this->body = $this->header . $this->body; - $boundary = '----==' . uniqid(rand(), TRUE); - $this->header = "Content-Type: multipart/mixed;" . $this->eol . "\tboundary=\"" . $boundary . "\"" . $this->eol . $this->eol; - $this->body = "--" . $boundary . $this->eol . $this->body . $this->eol . $this->eol; - $res = array(); - $res[] = $this->body; - foreach($this->attachments as $filename => $attachment) - { - $type = $this->returnMIMEType($filename); - $file_handler = new FileHandler(); - $file_str = $file_handler->readFile($attachment); - $chunks = chunk_split(base64_encode($file_str)); - $tempBody = sprintf( - "--" . $boundary . $this->eol . - "Content-Type: %s;" . $this->eol . - "\tname=\"%s\"" . $this->eol . - "Content-Transfer-Encoding: base64" . $this->eol . - "Content-Description: %s" . $this->eol . - "Content-Disposition: attachment;" . $this->eol . - "\tfilename=\"%s\"" . $this->eol . $this->eol . - "%s" . $this->eol . $this->eol, $type, $filename, $filename, $filename, $chunks); - $res[] = $tempBody; - } - $this->body = implode("", $res); - $this->body .= "--" . $boundary . "--"; - } - } - else - { - if(count($this->attachments) > 0) - { - foreach($this->attachments as $filename => $attachment) - { - parent::AddAttachment($attachment); - } - } - } + // no-op } - + /** * Process the images from body content. This functions is used if Mailer is set as mail not as SMTP - * + * * @return void */ - function procCidAttachments() + public function procCidAttachments() { - if(count($this->cidAttachments) > 0) - { - $this->body = $this->header . $this->body; - $boundary = '----==' . uniqid(rand(), TRUE); - $this->header = "Content-Type: multipart/relative;" . $this->eol . "\ttype=\"multipart/alternative\";" . $this->eol . "\tboundary=\"" . $boundary . "\"" . $this->eol . $this->eol; - $this->body = "--" . $boundary . $this->eol . $this->body . $this->eol . $this->eol; - $res = array(); - $res[] = $this->body; - foreach($this->cidAttachments as $cid => $attachment) - { - $filename = basename($attachment); - $type = $this->returnMIMEType(FileHandler::getRealPath($attachment)); - $file_str = FileHandler::readFile($attachment); - $chunks = chunk_split(base64_encode($file_str)); - $tempBody = sprintf( - "--" . $boundary . $this->eol . - "Content-Type: %s;" . $this->eol . - "\tname=\"%s\"" . $this->eol . - "Content-Transfer-Encoding: base64" . $this->eol . - "Content-ID: <%s>" . $this->eol . - "Content-Description: %s" . $this->eol . - "Content-Location: %s" . $this->eol . $this->eol . - "%s" . $this->eol . $this->eol, $type, $filename, $cid, $filename, $filename, $chunks); - $res[] = $tempBody; - } - $this->body = implode("", $res); - $this->body .= "--" . $boundary . "--"; - } + // no-op } - + + /** + * Process the message before sending + * + * @return void + */ + public function procAssembleMessage() + { + // Add all attachments + foreach($this->attachments as $original_filename => $filename) + { + $attachment = \Swift_Attachment::fromPath($original_filename); + $attachment->setFilename($filename); + $this->message->attach($attachment); + } + + // Add all CID attachments + foreach($this->cidAttachments as $cid => $original_filename) + { + $embedded = \Swift_EmbeddedFile::fromPath($original_filename); + $newcid = $this->message->embed($embedded); + $this->content = str_replace(array("cid:$cid", $cid), $newcid, $this->content); + } + + // Set content type + $content_type = $this->content_type === 'html' ? 'text/html' : 'text/plain'; + $this->message->setBody($this->content, $content_type); + } + /** * Send email - * - * @return bool TRUE in case of success, FALSE if sending fails + * + * @return bool */ - function send() + public function send() { - if($this->Mailer == "mail") + try { - $boundary = '----==' . uniqid(rand(), TRUE); - $this->eol = $GLOBALS['_qmail_compatibility'] == "Y" ? "\n" : "\r\n"; - $this->header = "Content-Type: multipart/alternative;" . $this->eol . "\tboundary=\"" . $boundary . "\"" . $this->eol . $this->eol; - $this->body = sprintf( - "--%s" . $this->eol . - "Content-Type: text/plain; charset=utf-8; format=flowed" . $this->eol . - "Content-Transfer-Encoding: base64" . $this->eol . - "Content-Disposition: inline" . $this->eol . $this->eol . - "%s" . - "--%s" . $this->eol . - "Content-Type: text/html; charset=utf-8" . $this->eol . - "Content-Transfer-Encoding: base64" . $this->eol . - "Content-Disposition: inline" . $this->eol . $this->eol . - "%s" . - "--%s--" . - "", $boundary, $this->getPlainContent(), $boundary, $this->getHTMLContent(), $boundary - ); - $this->procCidAttachments(); - $this->procAttachments(); - $headers = sprintf( - "From: %s" . $this->eol . - "%s" . - "%s" . - "%s" . - "%s" . - "MIME-Version: 1.0" . $this->eol . "", $this->getSender(), $this->messageId ? ("Message-ID: <" . $this->messageId . ">" . $this->eol) : "", $this->replyTo ? ("Reply-To: <" . $this->replyTo . ">" . $this->eol) : "", $this->bcc ? ("Bcc: " . $this->bcc . $this->eol) : "", $this->references ? ("References: <" . $this->references . ">" . $this->eol . "In-Reply-To: <" . $this->references . ">" . $this->eol) : "" - ); - $headers .= $this->header; - if($this->additional_params) + $this->procAssembleMessage(); + if(!self::$transport) { - return mail($this->getReceiptor(), $this->getTitle(), $this->body, $headers, $this->additional_params); + self::$transport = \Swift_MailTransport::newInstance(); } - return mail($this->getReceiptor(), $this->getTitle(), $this->body, $headers); + $mailer = \Swift_Mailer::newInstance(self::$transport); + $result = $mailer->send($this->message, $this->errors); + return (bool)$result; } - else + catch(\Exception $e) { - $this->procAttachments(); - return parent::Send(); + $this->error = $e->getMessage(); + return false; } } - + /** * Check if DNS of param is real or fake - * - * @param string $email_address Email address - * @return boolean TRUE if param is valid DNS otherwise FALSE + * + * @param string $email_address Email address to check + * @return bool */ - function checkMailMX($email_address) + public function checkMailMX($email_address) { - if(!Mail::isVaildMailAddress($email_address)) + if(!self::isVaildMailAddress($email_address)) { return FALSE; } @@ -612,14 +438,14 @@ class Mail extends PHPMailer } return TRUE; } - + /** * Check if param is a valid email or not - * - * @param string $email_address Email address - * @return string email address if param is valid email address otherwise blank string + * + * @param string $email_address Email address to check + * @return string */ - function isVaildMailAddress($email_address) + public function isVaildMailAddress($email_address) { if(preg_match("/([a-z0-9\_\-\.]+)@([a-z0-9\_\-\.]+)/i", $email_address)) { diff --git a/libs/phpmailer/LICENSE b/libs/phpmailer/LICENSE deleted file mode 100644 index 0d3dec198..000000000 --- a/libs/phpmailer/LICENSE +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/libs/phpmailer/class.phpmailer.php b/libs/phpmailer/class.phpmailer.php deleted file mode 100644 index afb71b25f..000000000 --- a/libs/phpmailer/class.phpmailer.php +++ /dev/null @@ -1,1909 +0,0 @@ -ContentType = 'text/html'; - } else { - $this->ContentType = 'text/plain'; - } - } - - /** - * Sets Mailer to send message using SMTP. - * @return void - */ - function IsSMTP() { - $this->Mailer = 'smtp'; - } - - /** - * Sets Mailer to send message using PHP mail() function. - * @return void - */ - function IsMail() { - $this->Mailer = 'mail'; - } - - /** - * Sets Mailer to send message using the $Sendmail program. - * @return void - */ - function IsSendmail() { - $this->Mailer = 'sendmail'; - } - - /** - * Sets Mailer to send message using the qmail MTA. - * @return void - */ - function IsQmail() { - $this->Sendmail = '/var/qmail/bin/sendmail'; - $this->Mailer = 'sendmail'; - } - - ///////////////////////////////////////////////// - // METHODS, RECIPIENTS - ///////////////////////////////////////////////// - - /** - * Adds a "To" address. - * @param string $address - * @param string $name - * @return void - */ - function AddAddress($address, $name = '') { - $cur = count($this->to); - $this->to[$cur][0] = trim($address); - $this->to[$cur][1] = $name; - } - - /** - * Adds a "Cc" address. Note: this function works - * with the SMTP mailer on win32, not with the "mail" - * mailer. - * @param string $address - * @param string $name - * @return void - */ - function AddCC($address, $name = '') { - $cur = count($this->cc); - $this->cc[$cur][0] = trim($address); - $this->cc[$cur][1] = $name; - } - - /** - * Adds a "Bcc" address. Note: this function works - * with the SMTP mailer on win32, not with the "mail" - * mailer. - * @param string $address - * @param string $name - * @return void - */ - function AddBCC($address, $name = '') { - $cur = count($this->bcc); - $this->bcc[$cur][0] = trim($address); - $this->bcc[$cur][1] = $name; - } - - /** - * Adds a "Reply-To" address. - * @param string $address - * @param string $name - * @return void - */ - function AddReplyTo($address, $name = '') { - $cur = count($this->ReplyTo); - $this->ReplyTo[$cur][0] = trim($address); - $this->ReplyTo[$cur][1] = $name; - } - - ///////////////////////////////////////////////// - // METHODS, MAIL SENDING - ///////////////////////////////////////////////// - - /** - * Creates message and assigns Mailer. If the message is - * not sent successfully then it returns false. Use the ErrorInfo - * variable to view description of the error. - * @return bool - */ - function Send() { - $header = ''; - $body = ''; - $result = true; - - if((count($this->to) + count($this->cc) + count($this->bcc)) < 1) { - $this->SetError($this->Lang('provide_address')); - return false; - } - - /* Set whether the message is multipart/alternative */ - if(!empty($this->AltBody)) { - $this->ContentType = 'multipart/alternative'; - } - - $this->error_count = 0; // reset errors - $this->SetMessageType(); - $header .= $this->CreateHeader(); - $body = $this->CreateBody(); - - if($body == '') { - return false; - } - - /* Choose the mailer */ - switch($this->Mailer) { - case 'sendmail': - $result = $this->SendmailSend($header, $body); - break; - case 'smtp': - $result = $this->SmtpSend($header, $body); - break; - case 'mail': - $result = $this->MailSend($header, $body); - break; - default: - $result = $this->MailSend($header, $body); - break; - //$this->SetError($this->Mailer . $this->Lang('mailer_not_supported')); - //$result = false; - //break; - } - - return $result; - } - - /** - * Sends mail using the $Sendmail program. - * @access private - * @return bool - */ - function SendmailSend($header, $body) { - if ($this->Sender != '') { - $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); - } else { - $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail)); - } - - if(!@$mail = popen($sendmail, 'w')) { - $this->SetError($this->Lang('execute') . $this->Sendmail); - return false; - } - - fputs($mail, $header); - fputs($mail, $body); - - $result = pclose($mail); - if (version_compare(phpversion(), '4.2.3') == -1) { - $result = $result >> 8 & 0xFF; - } - if($result != 0) { - $this->SetError($this->Lang('execute') . $this->Sendmail); - return false; - } - return true; - } - - /** - * Sends mail using the PHP mail() function. - * @access private - * @return bool - */ - function MailSend($header, $body) { - - $to = ''; - for($i = 0; $i < count($this->to); $i++) { - if($i != 0) { $to .= ', '; } - $to .= $this->AddrFormat($this->to[$i]); - } - - $toArr = split(',', $to); - - $params = sprintf("-oi -f %s", $this->Sender); - if ($this->Sender != '' && strlen(ini_get('safe_mode')) < 1) { - $old_from = ini_get('sendmail_from'); - ini_set('sendmail_from', $this->Sender); - if ($this->SingleTo === true && count($toArr) > 1) { - foreach ($toArr as $key => $val) { - $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); - } - } else { - $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); - } - } else { - if ($this->SingleTo === true && count($toArr) > 1) { - foreach ($toArr as $key => $val) { - $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); - } - } else { - $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header); - } - } - - if (isset($old_from)) { - ini_set('sendmail_from', $old_from); - } - - if(!$rt) { - $this->SetError($this->Lang('instantiate')); - return false; - } - - return true; - } - - /** - * Sends mail via SMTP using PhpSMTP (Author: - * Chris Ryan). Returns bool. Returns false if there is a - * bad MAIL FROM, RCPT, or DATA input. - * @access private - * @return bool - */ - function SmtpSend($header, $body) { - include_once($this->PluginDir . 'class.smtp.php'); - $error = ''; - $bad_rcpt = array(); - - if(!$this->SmtpConnect()) { - return false; - } - - $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender; - if(!$this->smtp->Mail($smtp_from)) { - $error = $this->Lang('from_failed') . $smtp_from; - $this->SetError($error); - $this->smtp->Reset(); - return false; - } - - /* Attempt to send attach all recipients */ - for($i = 0; $i < count($this->to); $i++) { - if(!$this->smtp->Recipient($this->to[$i][0])) { - $bad_rcpt[] = $this->to[$i][0]; - } - } - for($i = 0; $i < count($this->cc); $i++) { - if(!$this->smtp->Recipient($this->cc[$i][0])) { - $bad_rcpt[] = $this->cc[$i][0]; - } - } - for($i = 0; $i < count($this->bcc); $i++) { - if(!$this->smtp->Recipient($this->bcc[$i][0])) { - $bad_rcpt[] = $this->bcc[$i][0]; - } - } - - if(count($bad_rcpt) > 0) { // Create error message - for($i = 0; $i < count($bad_rcpt); $i++) { - if($i != 0) { - $error .= ', '; - } - $error .= $bad_rcpt[$i]; - } - $error = $this->Lang('recipients_failed') . $error; - $this->SetError($error); - $this->smtp->Reset(); - return false; - } - - if(!$this->smtp->Data($header . $body)) { - $this->SetError($this->Lang('data_not_accepted')); - $this->smtp->Reset(); - return false; - } - if($this->SMTPKeepAlive == true) { - $this->smtp->Reset(); - } else { - $this->SmtpClose(); - } - - return true; - } - - /** - * Initiates a connection to an SMTP server. Returns false if the - * operation failed. - * @access private - * @return bool - */ - function SmtpConnect() { - if($this->smtp == NULL) { - $this->smtp = new SMTP(); - } - - $this->smtp->do_debug = $this->SMTPDebug; - $hosts = explode(';', $this->Host); - $index = 0; - $connection = ($this->smtp->Connected()); - - /* Retry while there is no connection */ - while($index < count($hosts) && $connection == false) { - $hostinfo = array(); - if(eregi('^(.+):([0-9]+)$', $hosts[$index], $hostinfo)) { - $host = $hostinfo[1]; - $port = $hostinfo[2]; - } else { - $host = $hosts[$index]; - $port = $this->Port; - } - - if($this->smtp->Connect(((!empty($this->SMTPSecure))?$this->SMTPSecure.'://':'').$host, $port, $this->Timeout)) { - if ($this->Helo != '') { - $this->smtp->Hello($this->Helo); - } else { - $this->smtp->Hello($this->ServerHostname()); - } - - $connection = true; - if($this->SMTPAuth) { - if(!$this->smtp->Authenticate($this->Username, $this->Password)) { - $this->SetError($this->Lang('authenticate')); - $this->smtp->Reset(); - $connection = false; - } - } - } - $index++; - } - if(!$connection) { - $this->SetError($this->Lang('connect_host')); - } - - return $connection; - } - - /** - * Closes the active SMTP session if one exists. - * @return void - */ - function SmtpClose() { - if($this->smtp != NULL) { - if($this->smtp->Connected()) { - $this->smtp->Quit(); - $this->smtp->Close(); - } - } - } - - /** - * Sets the language for all class error messages. Returns false - * if it cannot load the language file. The default language type - * is English. - * @param string $lang_type Type of language (e.g. Portuguese: "br") - * @param string $lang_path Path to the language file directory - * @access public - * @return bool - */ - function SetLanguage($lang_type, $lang_path = 'language/') { - if(file_exists($lang_path.'phpmailer.lang-'.$lang_type.'.php')) { - include($lang_path.'phpmailer.lang-'.$lang_type.'.php'); - } elseif (file_exists($lang_path.'phpmailer.lang-en.php')) { - include($lang_path.'phpmailer.lang-en.php'); - } else { - $PHPMAILER_LANG = array(); - $PHPMAILER_LANG["provide_address"] = 'You must provide at least one ' . - $PHPMAILER_LANG["mailer_not_supported"] = ' mailer is not supported.'; - $PHPMAILER_LANG["execute"] = 'Could not execute: '; - $PHPMAILER_LANG["instantiate"] = 'Could not instantiate mail function.'; - $PHPMAILER_LANG["authenticate"] = 'SMTP Error: Could not authenticate.'; - $PHPMAILER_LANG["from_failed"] = 'The following From address failed: '; - $PHPMAILER_LANG["recipients_failed"] = 'SMTP Error: The following ' . - $PHPMAILER_LANG["data_not_accepted"] = 'SMTP Error: Data not accepted.'; - $PHPMAILER_LANG["connect_host"] = 'SMTP Error: Could not connect to SMTP host.'; - $PHPMAILER_LANG["file_access"] = 'Could not access file: '; - $PHPMAILER_LANG["file_open"] = 'File Error: Could not open file: '; - $PHPMAILER_LANG["encoding"] = 'Unknown encoding: '; - $PHPMAILER_LANG["signing"] = 'Signing Error: '; - } - $this->language = $PHPMAILER_LANG; - - return true; - } - - ///////////////////////////////////////////////// - // METHODS, MESSAGE CREATION - ///////////////////////////////////////////////// - - /** - * Creates recipient headers. - * @access private - * @return string - */ - function AddrAppend($type, $addr) { - $addr_str = $type . ': '; - $addr_str .= $this->AddrFormat($addr[0]); - if(count($addr) > 1) { - for($i = 1; $i < count($addr); $i++) { - $addr_str .= ', ' . $this->AddrFormat($addr[$i]); - } - } - $addr_str .= $this->LE; - - return $addr_str; - } - - /** - * Formats an address correctly. - * @access private - * @return string - */ - function AddrFormat($addr) { - if(empty($addr[1])) { - $formatted = $this->SecureHeader($addr[0]); - } else { - $formatted = $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">"; - } - - return $formatted; - } - - /** - * Wraps message for use with mailers that do not - * automatically perform wrapping and for quoted-printable. - * Original written by philippe. - * @access private - * @return string - */ - function WrapText($message, $length, $qp_mode = false) { - $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE; - // If utf-8 encoding is used, we will need to make sure we don't - // split multibyte characters when we wrap - $is_utf8 = (strtolower($this->CharSet) == "utf-8"); - - $message = $this->FixEOL($message); - if (substr($message, -1) == $this->LE) { - $message = substr($message, 0, -1); - } - - $line = explode($this->LE, $message); - $message = ''; - for ($i=0 ;$i < count($line); $i++) { - $line_part = explode(' ', $line[$i]); - $buf = ''; - for ($e = 0; $e $length)) { - $space_left = $length - strlen($buf) - 1; - if ($e != 0) { - if ($space_left > 20) { - $len = $space_left; - if ($is_utf8) { - $len = $this->UTF8CharBoundary($word, $len); - } elseif (substr($word, $len - 1, 1) == "=") { - $len--; - } elseif (substr($word, $len - 2, 1) == "=") { - $len -= 2; - } - $part = substr($word, 0, $len); - $word = substr($word, $len); - $buf .= ' ' . $part; - $message .= $buf . sprintf("=%s", $this->LE); - } else { - $message .= $buf . $soft_break; - } - $buf = ''; - } - while (strlen($word) > 0) { - $len = $length; - if ($is_utf8) { - $len = $this->UTF8CharBoundary($word, $len); - } elseif (substr($word, $len - 1, 1) == "=") { - $len--; - } elseif (substr($word, $len - 2, 1) == "=") { - $len -= 2; - } - $part = substr($word, 0, $len); - $word = substr($word, $len); - - if (strlen($word) > 0) { - $message .= $part . sprintf("=%s", $this->LE); - } else { - $buf = $part; - } - } - } else { - $buf_o = $buf; - $buf .= ($e == 0) ? $word : (' ' . $word); - - if (strlen($buf) > $length and $buf_o != '') { - $message .= $buf_o . $soft_break; - $buf = $word; - } - } - } - $message .= $buf . $this->LE; - } - - return $message; - } - - /** - * Finds last character boundary prior to maxLength in a utf-8 - * quoted (printable) encoded string. - * Original written by Colin Brown. - * @access private - * @param string $encodedText utf-8 QP text - * @param int $maxLength find last character boundary prior to this length - * @return int - */ - function UTF8CharBoundary($encodedText, $maxLength) { - $foundSplitPos = false; - $lookBack = 3; - while (!$foundSplitPos) { - $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack); - $encodedCharPos = strpos($lastChunk, "="); - if ($encodedCharPos !== false) { - // Found start of encoded character byte within $lookBack block. - // Check the encoded byte value (the 2 chars after the '=') - $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2); - $dec = hexdec($hex); - if ($dec < 128) { // Single byte character. - // If the encoded char was found at pos 0, it will fit - // otherwise reduce maxLength to start of the encoded char - $maxLength = ($encodedCharPos == 0) ? $maxLength : - $maxLength - ($lookBack - $encodedCharPos); - $foundSplitPos = true; - } elseif ($dec >= 192) { // First byte of a multi byte character - // Reduce maxLength to split at start of character - $maxLength = $maxLength - ($lookBack - $encodedCharPos); - $foundSplitPos = true; - } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back - $lookBack += 3; - } - } else { - // No encoded character found - $foundSplitPos = true; - } - } - return $maxLength; - } - - /** - * Set the body wrapping. - * @access private - * @return void - */ - function SetWordWrap() { - if($this->WordWrap < 1) { - return; - } - - switch($this->message_type) { - case 'alt': - /* fall through */ - case 'alt_attachments': - $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap); - break; - default: - $this->Body = $this->WrapText($this->Body, $this->WordWrap); - break; - } - } - - /** - * Assembles message header. - * @access private - * @return string - */ - function CreateHeader() { - $result = ''; - - /* Set the boundaries */ - $uniq_id = md5(uniqid(time())); - $this->boundary[1] = 'b1_' . $uniq_id; - $this->boundary[2] = 'b2_' . $uniq_id; - - $result .= $this->HeaderLine('Date', $this->RFCDate()); - if($this->Sender == '') { - $result .= $this->HeaderLine('Return-Path', trim($this->From)); - } else { - $result .= $this->HeaderLine('Return-Path', trim($this->Sender)); - } - - /* To be created automatically by mail() */ - if($this->Mailer != 'mail') { - if(count($this->to) > 0) { - $result .= $this->AddrAppend('To', $this->to); - } elseif (count($this->cc) == 0) { - $result .= $this->HeaderLine('To', 'undisclosed-recipients:;'); - } - } - - $from = array(); - $from[0][0] = trim($this->From); - $from[0][1] = $this->FromName; - $result .= $this->AddrAppend('From', $from); - - /* sendmail and mail() extract Cc from the header before sending */ - if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->cc) > 0)) { - $result .= $this->AddrAppend('Cc', $this->cc); - } - - /* sendmail and mail() extract Bcc from the header before sending */ - if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) { - $result .= $this->AddrAppend('Bcc', $this->bcc); - } - - if(count($this->ReplyTo) > 0) { - $result .= $this->AddrAppend('Reply-To', $this->ReplyTo); - } - - /* mail() sets the subject itself */ - if($this->Mailer != 'mail') { - $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject))); - } - - if($this->MessageID != '') { - $result .= $this->HeaderLine('Message-ID',$this->MessageID); - } else { - $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE); - } - $result .= $this->HeaderLine('X-Priority', $this->Priority); - $result .= $this->HeaderLine('X-Mailer', 'PHPMailer (phpmailer.sourceforge.net) [version ' . $this->Version . ']'); - - if($this->ConfirmReadingTo != '') { - $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>'); - } - - // Add custom headers - for($index = 0; $index < count($this->CustomHeader); $index++) { - $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1]))); - } - if (!$this->sign_key_file) { - $result .= $this->HeaderLine('MIME-Version', '1.0'); - $result .= $this->GetMailMIME(); - } - - return $result; - } - - /** - * Returns the message MIME. - * @access private - * @return string - */ - function GetMailMIME() { - $result = ''; - switch($this->message_type) { - case 'plain': - $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding); - $result .= sprintf("Content-Type: %s; charset=\"%s\"", $this->ContentType, $this->CharSet); - break; - case 'attachments': - /* fall through */ - case 'alt_attachments': - if($this->InlineImageExists()){ - $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE); - } else { - $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;'); - $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); - } - break; - case 'alt': - $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;'); - $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); - break; - } - - if($this->Mailer != 'mail') { - $result .= $this->LE.$this->LE; - } - - return $result; - } - - /** - * Assembles the message body. Returns an empty string on failure. - * @access private - * @return string - */ - function CreateBody() { - $result = ''; - if ($this->sign_key_file) { - $result .= $this->GetMailMIME(); - } - - $this->SetWordWrap(); - - switch($this->message_type) { - case 'alt': - $result .= $this->GetBoundary($this->boundary[1], '', 'text/plain', ''); - $result .= $this->EncodeString($this->AltBody, $this->Encoding); - $result .= $this->LE.$this->LE; - $result .= $this->GetBoundary($this->boundary[1], '', 'text/html', ''); - $result .= $this->EncodeString($this->Body, $this->Encoding); - $result .= $this->LE.$this->LE; - $result .= $this->EndBoundary($this->boundary[1]); - break; - case 'plain': - $result .= $this->EncodeString($this->Body, $this->Encoding); - break; - case 'attachments': - $result .= $this->GetBoundary($this->boundary[1], '', '', ''); - $result .= $this->EncodeString($this->Body, $this->Encoding); - $result .= $this->LE; - $result .= $this->AttachAll(); - break; - case 'alt_attachments': - $result .= sprintf("--%s%s", $this->boundary[1], $this->LE); - $result .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE); - $result .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body - $result .= $this->EncodeString($this->AltBody, $this->Encoding); - $result .= $this->LE.$this->LE; - $result .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body - $result .= $this->EncodeString($this->Body, $this->Encoding); - $result .= $this->LE.$this->LE; - $result .= $this->EndBoundary($this->boundary[2]); - $result .= $this->AttachAll(); - break; - } - - if($this->IsError()) { - $result = ''; - } else if ($this->sign_key_file) { - $file = tempnam("", "mail"); - $fp = fopen($file, "w"); - fwrite($fp, $result); - fclose($fp); - $signed = tempnam("", "signed"); - - if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), null)) { - $fp = fopen($signed, "r"); - $result = fread($fp, filesize($this->sign_key_file)); - $result = ''; - while(!feof($fp)){ - $result = $result . fread($fp, 1024); - } - fclose($fp); - } else { - $this->SetError($this->Lang("signing").openssl_error_string()); - $result = ''; - } - - unlink($file); - unlink($signed); - } - - return $result; - } - - /** - * Returns the start of a message boundary. - * @access private - */ - function GetBoundary($boundary, $charSet, $contentType, $encoding) { - $result = ''; - if($charSet == '') { - $charSet = $this->CharSet; - } - if($contentType == '') { - $contentType = $this->ContentType; - } - if($encoding == '') { - $encoding = $this->Encoding; - } - $result .= $this->TextLine('--' . $boundary); - $result .= sprintf("Content-Type: %s; charset = \"%s\"", $contentType, $charSet); - $result .= $this->LE; - $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding); - $result .= $this->LE; - - return $result; - } - - /** - * Returns the end of a message boundary. - * @access private - */ - function EndBoundary($boundary) { - return $this->LE . '--' . $boundary . '--' . $this->LE; - } - - /** - * Sets the message type. - * @access private - * @return void - */ - function SetMessageType() { - if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) { - $this->message_type = 'plain'; - } else { - if(count($this->attachment) > 0) { - $this->message_type = 'attachments'; - } - if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) { - $this->message_type = 'alt'; - } - if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) { - $this->message_type = 'alt_attachments'; - } - } - } - - /* Returns a formatted header line. - * @access private - * @return string - */ - function HeaderLine($name, $value) { - return $name . ': ' . $value . $this->LE; - } - - /** - * Returns a formatted mail line. - * @access private - * @return string - */ - function TextLine($value) { - return $value . $this->LE; - } - - ///////////////////////////////////////////////// - // CLASS METHODS, ATTACHMENTS - ///////////////////////////////////////////////// - - /** - * Adds an attachment from a path on the filesystem. - * Returns false if the file could not be found - * or accessed. - * @param string $path Path to the attachment. - * @param string $name Overrides the attachment name. - * @param string $encoding File encoding (see $Encoding). - * @param string $type File extension (MIME) type. - * @return bool - */ - function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { - if(!@is_file($path)) { - $this->SetError($this->Lang('file_access') . $path); - return false; - } - - $filename = basename($path); - if($name == '') { - $name = $filename; - } - - $cur = count($this->attachment); - $this->attachment[$cur][0] = $path; - $this->attachment[$cur][1] = $filename; - $this->attachment[$cur][2] = $name; - $this->attachment[$cur][3] = $encoding; - $this->attachment[$cur][4] = $type; - $this->attachment[$cur][5] = false; // isStringAttachment - $this->attachment[$cur][6] = 'attachment'; - $this->attachment[$cur][7] = 0; - - return true; - } - - /** - * Attaches all fs, string, and binary attachments to the message. - * Returns an empty string on failure. - * @access private - * @return string - */ - function AttachAll() { - /* Return text of body */ - $mime = array(); - - /* Add all attachments */ - for($i = 0; $i < count($this->attachment); $i++) { - /* Check for string attachment */ - $bString = $this->attachment[$i][5]; - if ($bString) { - $string = $this->attachment[$i][0]; - } else { - $path = $this->attachment[$i][0]; - } - - $filename = $this->attachment[$i][1]; - $name = $this->attachment[$i][2]; - $encoding = $this->attachment[$i][3]; - $type = $this->attachment[$i][4]; - $disposition = $this->attachment[$i][6]; - $cid = $this->attachment[$i][7]; - - $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE); - $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE); - $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE); - - if($disposition == 'inline') { - $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE); - } - - $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE); - - /* Encode as string attachment */ - if($bString) { - $mime[] = $this->EncodeString($string, $encoding); - if($this->IsError()) { - return ''; - } - $mime[] = $this->LE.$this->LE; - } else { - $mime[] = $this->EncodeFile($path, $encoding); - if($this->IsError()) { - return ''; - } - $mime[] = $this->LE.$this->LE; - } - } - - $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE); - - return join('', $mime); - } - - /** - * Encodes attachment in requested format. Returns an - * empty string on failure. - * @access private - * @return string - */ - function EncodeFile ($path, $encoding = 'base64') { - if(!@$fd = fopen($path, 'rb')) { - $this->SetError($this->Lang('file_open') . $path); - return ''; - } - $magic_quotes = get_magic_quotes_runtime(); - set_magic_quotes_runtime(0); - $file_buffer = fread($fd, filesize($path)); - $file_buffer = $this->EncodeString($file_buffer, $encoding); - fclose($fd); - set_magic_quotes_runtime($magic_quotes); - - return $file_buffer; - } - - /** - * Encodes string to requested format. Returns an - * empty string on failure. - * @access private - * @return string - */ - function EncodeString ($str, $encoding = 'base64') { - $encoded = ''; - switch(strtolower($encoding)) { - case 'base64': - /* chunk_split is found in PHP >= 3.0.6 */ - $encoded = chunk_split(base64_encode($str), 76, $this->LE); - break; - case '7bit': - case '8bit': - $encoded = $this->FixEOL($str); - if (substr($encoded, -(strlen($this->LE))) != $this->LE) - $encoded .= $this->LE; - break; - case 'binary': - $encoded = $str; - break; - case 'quoted-printable': - $encoded = $this->EncodeQP($str); - break; - default: - $this->SetError($this->Lang('encoding') . $encoding); - break; - } - return $encoded; - } - - /** - * Encode a header string to best of Q, B, quoted or none. - * @access private - * @return string - */ - function EncodeHeader ($str, $position = 'text') { - $x = 0; - - switch (strtolower($position)) { - case 'phrase': - if (!preg_match('/[\200-\377]/', $str)) { - /* Can't use addslashes as we don't know what value has magic_quotes_sybase. */ - $encoded = addcslashes($str, "\0..\37\177\\\""); - if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) { - return ($encoded); - } else { - return ("\"$encoded\""); - } - } - $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches); - break; - case 'comment': - $x = preg_match_all('/[()"]/', $str, $matches); - /* Fall-through */ - case 'text': - default: - $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches); - break; - } - - if ($x == 0) { - return ($str); - } - - $maxlen = 75 - 7 - strlen($this->CharSet); - /* Try to select the encoding which should produce the shortest output */ - if (strlen($str)/3 < $x) { - $encoding = 'B'; - if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) { - // Use a custom function which correctly encodes and wraps long - // multibyte strings without breaking lines within a character - $encoded = $this->Base64EncodeWrapMB($str); - } else { - $encoded = base64_encode($str); - $maxlen -= $maxlen % 4; - $encoded = trim(chunk_split($encoded, $maxlen, "\n")); - } - } else { - $encoding = 'Q'; - $encoded = $this->EncodeQ($str, $position); - $encoded = $this->WrapText($encoded, $maxlen, true); - $encoded = str_replace('='.$this->LE, "\n", trim($encoded)); - } - - $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded); - $encoded = trim(str_replace("\n", $this->LE, $encoded)); - - return $encoded; - } - - /** - * Checks if a string contains multibyte characters. - * @access private - * @param string $str multi-byte text to wrap encode - * @return bool - */ - function HasMultiBytes($str) { - if (function_exists('mb_strlen')) { - return (strlen($str) > mb_strlen($str, $this->CharSet)); - } else { // Assume no multibytes (we can't handle without mbstring functions anyway) - return False; - } - } - - /** - * Correctly encodes and wraps long multibyte strings for mail headers - * without breaking lines within a character. - * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php - * @access private - * @param string $str multi-byte text to wrap encode - * @return string - */ - function Base64EncodeWrapMB($str) { - $start = "=?".$this->CharSet."?B?"; - $end = "?="; - $encoded = ""; - - $mb_length = mb_strlen($str, $this->CharSet); - // Each line must have length <= 75, including $start and $end - $length = 75 - strlen($start) - strlen($end); - // Average multi-byte ratio - $ratio = $mb_length / strlen($str); - // Base64 has a 4:3 ratio - $offset = $avgLength = floor($length * $ratio * .75); - - for ($i = 0; $i < $mb_length; $i += $offset) { - $lookBack = 0; - - do { - $offset = $avgLength - $lookBack; - $chunk = mb_substr($str, $i, $offset, $this->CharSet); - $chunk = base64_encode($chunk); - $lookBack++; - } - while (strlen($chunk) > $length); - - $encoded .= $chunk . $this->LE; - } - - // Chomp the last linefeed - $encoded = substr($encoded, 0, -strlen($this->LE)); - return $encoded; - } - - /** - * Encode string to quoted-printable. - * @access private - * @return string - */ - function EncodeQP( $input = '', $line_max = 76, $space_conv = false ) { - $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); - $lines = preg_split('/(?:\r\n|\r|\n)/', $input); - $eol = "\r\n"; - $escape = '='; - $output = ''; - while( list(, $line) = each($lines) ) { - $linlen = strlen($line); - $newline = ''; - for($i = 0; $i < $linlen; $i++) { - $c = substr( $line, $i, 1 ); - $dec = ord( $c ); - if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E - $c = '=2E'; - } - if ( $dec == 32 ) { - if ( $i == ( $linlen - 1 ) ) { // convert space at eol only - $c = '=20'; - } else if ( $space_conv ) { - $c = '=20'; - } - } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required - $h2 = floor($dec/16); - $h1 = floor($dec%16); - $c = $escape.$hex[$h2].$hex[$h1]; - } - if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted - $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay - $newline = ''; - // check if newline first character will be point or not - if ( $dec == 46 ) { - $c = '=2E'; - } - } - $newline .= $c; - } // end of for - $output .= $newline.$eol; - } // end of while - return $output; - } - - /** - * Encode string to q encoding. - * @access private - * @return string - */ - function EncodeQ ($str, $position = 'text') { - /* There should not be any EOL in the string */ - $encoded = preg_replace("[\r\n]", '', $str); - - switch (strtolower($position)) { - case 'phrase': - $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); - break; - case 'comment': - $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); - case 'text': - default: - /* Replace every high ascii, control =, ? and _ characters */ - $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e', - "'='.sprintf('%02X', ord('\\1'))", $encoded); - break; - } - - /* Replace every spaces to _ (more readable than =20) */ - $encoded = str_replace(' ', '_', $encoded); - - return $encoded; - } - - /** - * Adds a string or binary attachment (non-filesystem) to the list. - * This method can be used to attach ascii or binary data, - * such as a BLOB record from a database. - * @param string $string String attachment data. - * @param string $filename Name of the attachment. - * @param string $encoding File encoding (see $Encoding). - * @param string $type File extension (MIME) type. - * @return void - */ - function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') { - /* Append to $attachment array */ - $cur = count($this->attachment); - $this->attachment[$cur][0] = $string; - $this->attachment[$cur][1] = $filename; - $this->attachment[$cur][2] = $filename; - $this->attachment[$cur][3] = $encoding; - $this->attachment[$cur][4] = $type; - $this->attachment[$cur][5] = true; // isString - $this->attachment[$cur][6] = 'attachment'; - $this->attachment[$cur][7] = 0; - } - - /** - * Adds an embedded attachment. This can include images, sounds, and - * just about any other document. Make sure to set the $type to an - * image type. For JPEG images use "image/jpeg" and for GIF images - * use "image/gif". - * @param string $path Path to the attachment. - * @param string $cid Content ID of the attachment. Use this to identify - * the Id for accessing the image in an HTML form. - * @param string $name Overrides the attachment name. - * @param string $encoding File encoding (see $Encoding). - * @param string $type File extension (MIME) type. - * @return bool - */ - function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { - - if(!@is_file($path)) { - $this->SetError($this->Lang('file_access') . $path); - return false; - } - - $filename = basename($path); - if($name == '') { - $name = $filename; - } - - /* Append to $attachment array */ - $cur = count($this->attachment); - $this->attachment[$cur][0] = $path; - $this->attachment[$cur][1] = $filename; - $this->attachment[$cur][2] = $name; - $this->attachment[$cur][3] = $encoding; - $this->attachment[$cur][4] = $type; - $this->attachment[$cur][5] = false; - $this->attachment[$cur][6] = 'inline'; - $this->attachment[$cur][7] = $cid; - - return true; - } - - /** - * Returns true if an inline attachment is present. - * @access private - * @return bool - */ - function InlineImageExists() { - $result = false; - for($i = 0; $i < count($this->attachment); $i++) { - if($this->attachment[$i][6] == 'inline') { - $result = true; - break; - } - } - - return $result; - } - - ///////////////////////////////////////////////// - // CLASS METHODS, MESSAGE RESET - ///////////////////////////////////////////////// - - /** - * Clears all recipients assigned in the TO array. Returns void. - * @return void - */ - function ClearAddresses() { - $this->to = array(); - } - - /** - * Clears all recipients assigned in the CC array. Returns void. - * @return void - */ - function ClearCCs() { - $this->cc = array(); - } - - /** - * Clears all recipients assigned in the BCC array. Returns void. - * @return void - */ - function ClearBCCs() { - $this->bcc = array(); - } - - /** - * Clears all recipients assigned in the ReplyTo array. Returns void. - * @return void - */ - function ClearReplyTos() { - $this->ReplyTo = array(); - } - - /** - * Clears all recipients assigned in the TO, CC and BCC - * array. Returns void. - * @return void - */ - function ClearAllRecipients() { - $this->to = array(); - $this->cc = array(); - $this->bcc = array(); - } - - /** - * Clears all previously set filesystem, string, and binary - * attachments. Returns void. - * @return void - */ - function ClearAttachments() { - $this->attachment = array(); - } - - /** - * Clears all custom headers. Returns void. - * @return void - */ - function ClearCustomHeaders() { - $this->CustomHeader = array(); - } - - ///////////////////////////////////////////////// - // CLASS METHODS, MISCELLANEOUS - ///////////////////////////////////////////////// - - /** - * Adds the error message to the error container. - * Returns void. - * @access private - * @return void - */ - function SetError($msg) { - $this->error_count++; - $this->ErrorInfo = $msg; - } - - /** - * Returns the proper RFC 822 formatted date. - * @access private - * @return string - */ - function RFCDate() { - $tz = date('Z'); - $tzs = ($tz < 0) ? '-' : '+'; - $tz = abs($tz); - $tz = (int)($tz/3600)*100 + ($tz%3600)/60; - $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz); - - return $result; - } - - /** - * Returns the appropriate server variable. Should work with both - * PHP 4.1.0+ as well as older versions. Returns an empty string - * if nothing is found. - * @access private - * @return mixed - */ - function ServerVar($varName) { - global $HTTP_SERVER_VARS; - global $HTTP_ENV_VARS; - - if(!isset($_SERVER)) { - $_SERVER = $HTTP_SERVER_VARS; - if(!isset($_SERVER['REMOTE_ADDR'])) { - $_SERVER = $HTTP_ENV_VARS; // must be Apache - } - } - - if(isset($_SERVER[$varName])) { - return $_SERVER[$varName]; - } else { - return ''; - } - } - - /** - * Returns the server hostname or 'localhost.localdomain' if unknown. - * @access private - * @return string - */ - function ServerHostname() { - if ($this->Hostname != '') { - $result = $this->Hostname; - } elseif ($this->ServerVar('SERVER_NAME') != '') { - $result = $this->ServerVar('SERVER_NAME'); - } else { - $result = 'localhost.localdomain'; - } - - return $result; - } - - /** - * Returns a message in the appropriate language. - * @access private - * @return string - */ - function Lang($key) { - if(count($this->language) < 1) { - $this->SetLanguage('en'); // set the default language - } - - if(isset($this->language[$key])) { - return $this->language[$key]; - } else { - return 'Language string failed to load: ' . $key; - } - } - - /** - * Returns true if an error occurred. - * @return bool - */ - function IsError() { - return ($this->error_count > 0); - } - - /** - * Changes every end of line from CR or LF to CRLF. - * @access private - * @return string - */ - function FixEOL($str) { - $str = str_replace("\r\n", "\n", $str); - $str = str_replace("\r", "\n", $str); - $str = str_replace("\n", $this->LE, $str); - return $str; - } - - /** - * Adds a custom header. - * @return void - */ - function AddCustomHeader($custom_header) { - $this->CustomHeader[] = explode(':', $custom_header, 2); - } - - /** - * Evaluates the message and returns modifications for inline images and backgrounds - * @access public - * @return $message - */ - function MsgHTML($message,$basedir='') { - preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images); - if(isset($images[2])) { - foreach($images[2] as $i => $url) { - // do not change urls for absolute images (thanks to corvuscorax) - if (!preg_match('/^[A-z][A-z]*:\/\//',$url)) { - $filename = basename($url); - $directory = dirname($url); - ($directory == '.')?$directory='':''; - $cid = 'cid:' . md5($filename); - $fileParts = split("\.", $filename); - $ext = $fileParts[1]; - $mimeType = $this->_mime_types($ext); - if ( strlen($basedir) > 1 && substr($basedir,-1) != '/') { $basedir .= '/'; } - if ( strlen($directory) > 1 && substr($directory,-1) != '/') { $directory .= '/'; } - if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64',$mimeType) ) { - $message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message); - } - } - } - } - $this->IsHTML(true); - $this->Body = $message; - $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s','',$message))); - if ( !empty($textMsg) && empty($this->AltBody) ) { - $this->AltBody = html_entity_decode($textMsg); - } - if ( empty($this->AltBody) ) { - $this->AltBody = 'To view this email message, open the email in with HTML compatibility!' . "\n\n"; - } - } - - /** - * Gets the mime type of the embedded or inline image - * @access private - * @return mime type of ext - */ - function _mime_types($ext = '') { - $mimes = array( - 'ai' => 'application/postscript', - 'aif' => 'audio/x-aiff', - 'aifc' => 'audio/x-aiff', - 'aiff' => 'audio/x-aiff', - 'avi' => 'video/x-msvideo', - 'bin' => 'application/macbinary', - 'bmp' => 'image/bmp', - 'class' => 'application/octet-stream', - 'cpt' => 'application/mac-compactpro', - 'css' => 'text/css', - 'dcr' => 'application/x-director', - 'dir' => 'application/x-director', - 'dll' => 'application/octet-stream', - 'dms' => 'application/octet-stream', - 'doc' => 'application/msword', - 'dvi' => 'application/x-dvi', - 'dxr' => 'application/x-director', - 'eml' => 'message/rfc822', - 'eps' => 'application/postscript', - 'exe' => 'application/octet-stream', - 'gif' => 'image/gif', - 'gtar' => 'application/x-gtar', - 'htm' => 'text/html', - 'html' => 'text/html', - 'jpe' => 'image/jpeg', - 'jpeg' => 'image/jpeg', - 'jpg' => 'image/jpeg', - 'hqx' => 'application/mac-binhex40', - 'js' => 'application/x-javascript', - 'lha' => 'application/octet-stream', - 'log' => 'text/plain', - 'lzh' => 'application/octet-stream', - 'mid' => 'audio/midi', - 'midi' => 'audio/midi', - 'mif' => 'application/vnd.mif', - 'mov' => 'video/quicktime', - 'movie' => 'video/x-sgi-movie', - 'mp2' => 'audio/mpeg', - 'mp3' => 'audio/mpeg', - 'mpe' => 'video/mpeg', - 'mpeg' => 'video/mpeg', - 'mpg' => 'video/mpeg', - 'mpga' => 'audio/mpeg', - 'oda' => 'application/oda', - 'pdf' => 'application/pdf', - 'php' => 'application/x-httpd-php', - 'php3' => 'application/x-httpd-php', - 'php4' => 'application/x-httpd-php', - 'phps' => 'application/x-httpd-php-source', - 'phtml' => 'application/x-httpd-php', - 'png' => 'image/png', - 'ppt' => 'application/vnd.ms-powerpoint', - 'ps' => 'application/postscript', - 'psd' => 'application/octet-stream', - 'qt' => 'video/quicktime', - 'ra' => 'audio/x-realaudio', - 'ram' => 'audio/x-pn-realaudio', - 'rm' => 'audio/x-pn-realaudio', - 'rpm' => 'audio/x-pn-realaudio-plugin', - 'rtf' => 'text/rtf', - 'rtx' => 'text/richtext', - 'rv' => 'video/vnd.rn-realvideo', - 'sea' => 'application/octet-stream', - 'shtml' => 'text/html', - 'sit' => 'application/x-stuffit', - 'so' => 'application/octet-stream', - 'smi' => 'application/smil', - 'smil' => 'application/smil', - 'swf' => 'application/x-shockwave-flash', - 'tar' => 'application/x-tar', - 'text' => 'text/plain', - 'txt' => 'text/plain', - 'tgz' => 'application/x-tar', - 'tif' => 'image/tiff', - 'tiff' => 'image/tiff', - 'wav' => 'audio/x-wav', - 'wbxml' => 'application/vnd.wap.wbxml', - 'wmlc' => 'application/vnd.wap.wmlc', - 'word' => 'application/msword', - 'xht' => 'application/xhtml+xml', - 'xhtml' => 'application/xhtml+xml', - 'xl' => 'application/excel', - 'xls' => 'application/vnd.ms-excel', - 'xml' => 'text/xml', - 'xsl' => 'text/xml', - 'zip' => 'application/zip' - ); - return ( ! isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)]; - } - - /** - * Set (or reset) Class Objects (variables) - * - * Usage Example: - * $page->set('X-Priority', '3'); - * - * @access public - * @param string $name Parameter Name - * @param mixed $value Parameter Value - * NOTE: will not work with arrays, there are no arrays to set/reset - */ - function set ( $name, $value = '' ) { - if ( isset($this->$name) ) { - $this->$name = $value; - } else { - $this->SetError('Cannot set or reset variable ' . $name); - return false; - } - } - - /** - * Read a file from a supplied filename and return it. - * - * @access public - * @param string $filename Parameter File Name - */ - function getFile($filename) { - $return = ''; - if ($fp = fopen($filename, 'rb')) { - while (!feof($fp)) { - $return .= fread($fp, 1024); - } - fclose($fp); - return $return; - } else { - return false; - } - } - - /** - * Strips newlines to prevent header injection. - * @access private - * @param string $str String - * @return string - */ - function SecureHeader($str) { - $str = trim($str); - $str = str_replace("\r", "", $str); - $str = str_replace("\n", "", $str); - return $str; - } - - /** - * Set the private key file and password to sign the message. - * - * @access public - * @param string $key_filename Parameter File Name - * @param string $key_pass Password for private key - */ - function Sign($cert_filename, $key_filename, $key_pass) { - $this->sign_cert_file = $cert_filename; - $this->sign_key_file = $key_filename; - $this->sign_key_pass = $key_pass; - } - -} - -?> \ No newline at end of file diff --git a/libs/phpmailer/class.smtp.php b/libs/phpmailer/class.smtp.php deleted file mode 100644 index be084a116..000000000 --- a/libs/phpmailer/class.smtp.php +++ /dev/null @@ -1,1062 +0,0 @@ -smtp_conn = 0; - $this->error = null; - $this->helo_rply = null; - - $this->do_debug = 0; - } - - /************************************************************* - * CONNECTION FUNCTIONS * - ***********************************************************/ - - /** - * Connect to the server specified on the port specified. - * If the port is not specified use the default SMTP_PORT. - * If tval is specified then a connection will try and be - * established with the server for that number of seconds. - * If tval is not specified the default is 30 seconds to - * try on the connection. - * - * SMTP CODE SUCCESS: 220 - * SMTP CODE FAILURE: 421 - * @access public - * @return bool - */ - function Connect($host,$port=0,$tval=30) { - # set the error val to null so there is no confusion - $this->error = null; - - # make sure we are __not__ connected - if($this->connected()) { - # ok we are connected! what should we do? - # for now we will just give an error saying we - # are already connected - $this->error = array("error" => "Already connected to a server"); - return false; - } - - if(empty($port)) { - $port = $this->SMTP_PORT; - } - - #connect to the smtp server - $this->smtp_conn = fsockopen($host, # the host of the server - $port, # the port to use - $errno, # error number if any - $errstr, # error message if any - $tval); # give up after ? secs - # verify we connected properly - if(empty($this->smtp_conn)) { - $this->error = array("error" => "Failed to connect to server", - "errno" => $errno, - "errstr" => $errstr); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": $errstr ($errno)" . $this->CRLF; - } - return false; - } - - # sometimes the SMTP server takes a little longer to respond - # so we will give it a longer timeout for the first read - // Windows still does not have support for this timeout function - if(substr(PHP_OS, 0, 3) != "WIN") - socket_set_timeout($this->smtp_conn, $tval, 0); - - # get any announcement stuff - $announce = $this->get_lines(); - - # set the timeout of any socket functions at 1/10 of a second - //if(function_exists("socket_set_timeout")) - // socket_set_timeout($this->smtp_conn, 0, 100000); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce; - } - - return true; - } - - /** - * Performs SMTP authentication. Must be run after running the - * Hello() method. Returns true if successfully authenticated. - * @access public - * @return bool - */ - function Authenticate($username, $password) { - // Start authentication - fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($code != 334) { - $this->error = - array("error" => "AUTH not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - - // Send encoded username - fputs($this->smtp_conn, base64_encode($username) . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($code != 334) { - $this->error = - array("error" => "Username not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - - // Send encoded password - fputs($this->smtp_conn, base64_encode($password) . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($code != 235) { - $this->error = - array("error" => "Password not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - - return true; - } - - /** - * Returns true if connected to a server otherwise false - * @access private - * @return bool - */ - function Connected() { - if(!empty($this->smtp_conn)) { - $sock_status = socket_get_status($this->smtp_conn); - if($sock_status["eof"]) { - # hmm this is an odd situation... the socket is - # valid but we are not connected anymore - if($this->do_debug >= 1) { - echo "SMTP -> NOTICE:" . $this->CRLF . - "EOF caught while checking if connected"; - } - $this->Close(); - return false; - } - return true; # everything looks good - } - return false; - } - - /** - * Closes the socket and cleans up the state of the class. - * It is not considered good to use this function without - * first trying to use QUIT. - * @access public - * @return void - */ - function Close() { - $this->error = null; # so there is no confusion - $this->helo_rply = null; - if(!empty($this->smtp_conn)) { - # close the connection and cleanup - fclose($this->smtp_conn); - $this->smtp_conn = 0; - } - } - - /*************************************************************** - * SMTP COMMANDS * - *************************************************************/ - - /** - * Issues a data command and sends the msg_data to the server - * finializing the mail transaction. $msg_data is the message - * that is to be send with the headers. Each header needs to be - * on a single line followed by a with the message headers - * and the message body being seperated by and additional . - * - * Implements rfc 821: DATA - * - * SMTP CODE INTERMEDIATE: 354 - * [data] - * . - * SMTP CODE SUCCESS: 250 - * SMTP CODE FAILURE: 552,554,451,452 - * SMTP CODE FAILURE: 451,554 - * SMTP CODE ERROR : 500,501,503,421 - * @access public - * @return bool - */ - function Data($msg_data) { - $this->error = null; # so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Data() without being connected"); - return false; - } - - fputs($this->smtp_conn,"DATA" . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; - } - - if($code != 354) { - $this->error = - array("error" => "DATA command not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - - # the server is ready to accept data! - # according to rfc 821 we should not send more than 1000 - # including the CRLF - # characters on a single line so we will break the data up - # into lines by \r and/or \n then if needed we will break - # each of those into smaller lines to fit within the limit. - # in addition we will be looking for lines that start with - # a period '.' and append and additional period '.' to that - # line. NOTE: this does not count towards are limit. - - # normalize the line breaks so we know the explode works - $msg_data = str_replace("\r\n","\n",$msg_data); - $msg_data = str_replace("\r","\n",$msg_data); - $lines = explode("\n",$msg_data); - - # we need to find a good way to determine is headers are - # in the msg_data or if it is a straight msg body - # currently I am assuming rfc 822 definitions of msg headers - # and if the first field of the first line (':' sperated) - # does not contain a space then it _should_ be a header - # and we can process all lines before a blank "" line as - # headers. - $field = substr($lines[0],0,strpos($lines[0],":")); - $in_headers = false; - if(!empty($field) && !strstr($field," ")) { - $in_headers = true; - } - - $max_line_length = 998; # used below; set here for ease in change - - while(list(,$line) = @each($lines)) { - $lines_out = null; - if($line == "" && $in_headers) { - $in_headers = false; - } - # ok we need to break this line up into several - # smaller lines - while(strlen($line) > $max_line_length) { - $pos = strrpos(substr($line,0,$max_line_length)," "); - - # Patch to fix DOS attack - if(!$pos) { - $pos = $max_line_length - 1; - } - - $lines_out[] = substr($line,0,$pos); - $line = substr($line,$pos + 1); - # if we are processing headers we need to - # add a LWSP-char to the front of the new line - # rfc 822 on long msg headers - if($in_headers) { - $line = "\t" . $line; - } - } - $lines_out[] = $line; - - # now send the lines to the server - while(list(,$line_out) = @each($lines_out)) { - if(strlen($line_out) > 0) - { - if(substr($line_out, 0, 1) == ".") { - $line_out = "." . $line_out; - } - } - fputs($this->smtp_conn,$line_out . $this->CRLF); - } - } - - # ok all the message data has been sent so lets get this - # over with aleady - fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; - } - - if($code != 250) { - $this->error = - array("error" => "DATA not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - return true; - } - - /** - * Expand takes the name and asks the server to list all the - * people who are members of the _list_. Expand will return - * back and array of the result or false if an error occurs. - * Each value in the array returned has the format of: - * [ ] - * The definition of is defined in rfc 821 - * - * Implements rfc 821: EXPN - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE FAILURE: 550 - * SMTP CODE ERROR : 500,501,502,504,421 - * @access public - * @return string array - */ - function Expand($name) { - $this->error = null; # so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Expand() without being connected"); - return false; - } - - fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; - } - - if($code != 250) { - $this->error = - array("error" => "EXPN not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - - # parse the reply and place in our array to return to user - $entries = explode($this->CRLF,$rply); - while(list(,$l) = @each($entries)) { - $list[] = substr($l,4); - } - - return $list; - } - - /** - * Sends the HELO command to the smtp server. - * This makes sure that we and the server are in - * the same known state. - * - * Implements from rfc 821: HELO - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE ERROR : 500, 501, 504, 421 - * @access public - * @return bool - */ - function Hello($host="") { - $this->error = null; # so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Hello() without being connected"); - return false; - } - - # if a hostname for the HELO was not specified determine - # a suitable one to send - if(empty($host)) { - # we need to determine some sort of appopiate default - # to send to the server - $host = "localhost"; - } - - // Send extended hello first (RFC 2821) - if(!$this->SendHello("EHLO", $host)) - { - if(!$this->SendHello("HELO", $host)) - return false; - } - - return true; - } - - /** - * Sends a HELO/EHLO command. - * @access private - * @return bool - */ - function SendHello($hello, $host) { - fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply; - } - - if($code != 250) { - $this->error = - array("error" => $hello . " not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - - $this->helo_rply = $rply; - - return true; - } - - /** - * Gets help information on the keyword specified. If the keyword - * is not specified then returns generic help, ussually contianing - * A list of keywords that help is available on. This function - * returns the results back to the user. It is up to the user to - * handle the returned data. If an error occurs then false is - * returned with $this->error set appropiately. - * - * Implements rfc 821: HELP [ ] - * - * SMTP CODE SUCCESS: 211,214 - * SMTP CODE ERROR : 500,501,502,504,421 - * @access public - * @return string - */ - function Help($keyword="") { - $this->error = null; # to avoid confusion - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Help() without being connected"); - return false; - } - - $extra = ""; - if(!empty($keyword)) { - $extra = " " . $keyword; - } - - fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; - } - - if($code != 211 && $code != 214) { - $this->error = - array("error" => "HELP not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - - return $rply; - } - - /** - * Starts a mail transaction from the email address specified in - * $from. Returns true if successful or false otherwise. If True - * the mail transaction is started and then one or more Recipient - * commands may be called followed by a Data command. - * - * Implements rfc 821: MAIL FROM: - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE SUCCESS: 552,451,452 - * SMTP CODE SUCCESS: 500,501,421 - * @access public - * @return bool - */ - function Mail($from) { - $this->error = null; # so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Mail() without being connected"); - return false; - } - - $useVerp = ($this->do_verp ? "XVERP" : ""); - fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; - } - - if($code != 250) { - $this->error = - array("error" => "MAIL not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - return true; - } - - /** - * Sends the command NOOP to the SMTP server. - * - * Implements from rfc 821: NOOP - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE ERROR : 500, 421 - * @access public - * @return bool - */ - function Noop() { - $this->error = null; # so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Noop() without being connected"); - return false; - } - - fputs($this->smtp_conn,"NOOP" . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; - } - - if($code != 250) { - $this->error = - array("error" => "NOOP not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - return true; - } - - /** - * Sends the quit command to the server and then closes the socket - * if there is no error or the $close_on_error argument is true. - * - * Implements from rfc 821: QUIT - * - * SMTP CODE SUCCESS: 221 - * SMTP CODE ERROR : 500 - * @access public - * @return bool - */ - function Quit($close_on_error=true) { - $this->error = null; # so there is no confusion - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Quit() without being connected"); - return false; - } - - # send the quit command to the server - fputs($this->smtp_conn,"quit" . $this->CRLF); - - # get any good-bye messages - $byemsg = $this->get_lines(); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg; - } - - $rval = true; - $e = null; - - $code = substr($byemsg,0,3); - if($code != 221) { - # use e as a tmp var cause Close will overwrite $this->error - $e = array("error" => "SMTP server rejected quit command", - "smtp_code" => $code, - "smtp_rply" => substr($byemsg,4)); - $rval = false; - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $e["error"] . ": " . - $byemsg . $this->CRLF; - } - } - - if(empty($e) || $close_on_error) { - $this->Close(); - } - - return $rval; - } - - /** - * Sends the command RCPT to the SMTP server with the TO: argument of $to. - * Returns true if the recipient was accepted false if it was rejected. - * - * Implements from rfc 821: RCPT TO: - * - * SMTP CODE SUCCESS: 250,251 - * SMTP CODE FAILURE: 550,551,552,553,450,451,452 - * SMTP CODE ERROR : 500,501,503,421 - * @access public - * @return bool - */ - function Recipient($to) { - $this->error = null; # so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Recipient() without being connected"); - return false; - } - - fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; - } - - if($code != 250 && $code != 251) { - $this->error = - array("error" => "RCPT not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - return true; - } - - /** - * Sends the RSET command to abort and transaction that is - * currently in progress. Returns true if successful false - * otherwise. - * - * Implements rfc 821: RSET - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE ERROR : 500,501,504,421 - * @access public - * @return bool - */ - function Reset() { - $this->error = null; # so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Reset() without being connected"); - return false; - } - - fputs($this->smtp_conn,"RSET" . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; - } - - if($code != 250) { - $this->error = - array("error" => "RSET failed", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - - return true; - } - - /** - * Starts a mail transaction from the email address specified in - * $from. Returns true if successful or false otherwise. If True - * the mail transaction is started and then one or more Recipient - * commands may be called followed by a Data command. This command - * will send the message to the users terminal if they are logged - * in. - * - * Implements rfc 821: SEND FROM: - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE SUCCESS: 552,451,452 - * SMTP CODE SUCCESS: 500,501,502,421 - * @access public - * @return bool - */ - function Send($from) { - $this->error = null; # so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Send() without being connected"); - return false; - } - - fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; - } - - if($code != 250) { - $this->error = - array("error" => "SEND not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - return true; - } - - /** - * Starts a mail transaction from the email address specified in - * $from. Returns true if successful or false otherwise. If True - * the mail transaction is started and then one or more Recipient - * commands may be called followed by a Data command. This command - * will send the message to the users terminal if they are logged - * in and send them an email. - * - * Implements rfc 821: SAML FROM: - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE SUCCESS: 552,451,452 - * SMTP CODE SUCCESS: 500,501,502,421 - * @access public - * @return bool - */ - function SendAndMail($from) { - $this->error = null; # so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called SendAndMail() without being connected"); - return false; - } - - fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; - } - - if($code != 250) { - $this->error = - array("error" => "SAML not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - return true; - } - - /** - * Starts a mail transaction from the email address specified in - * $from. Returns true if successful or false otherwise. If True - * the mail transaction is started and then one or more Recipient - * commands may be called followed by a Data command. This command - * will send the message to the users terminal if they are logged - * in or mail it to them if they are not. - * - * Implements rfc 821: SOML FROM: - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE SUCCESS: 552,451,452 - * SMTP CODE SUCCESS: 500,501,502,421 - * @access public - * @return bool - */ - function SendOrMail($from) { - $this->error = null; # so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called SendOrMail() without being connected"); - return false; - } - - fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; - } - - if($code != 250) { - $this->error = - array("error" => "SOML not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - return true; - } - - /** - * This is an optional command for SMTP that this class does not - * support. This method is here to make the RFC821 Definition - * complete for this class and __may__ be implimented in the future - * - * Implements from rfc 821: TURN - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE FAILURE: 502 - * SMTP CODE ERROR : 500, 503 - * @access public - * @return bool - */ - function Turn() { - $this->error = array("error" => "This method, TURN, of the SMTP ". - "is not implemented"); - if($this->do_debug >= 1) { - echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF; - } - return false; - } - - /** - * Verifies that the name is recognized by the server. - * Returns false if the name could not be verified otherwise - * the response from the server is returned. - * - * Implements rfc 821: VRFY - * - * SMTP CODE SUCCESS: 250,251 - * SMTP CODE FAILURE: 550,551,553 - * SMTP CODE ERROR : 500,501,502,421 - * @access public - * @return int - */ - function Verify($name) { - $this->error = null; # so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Verify() without being connected"); - return false; - } - - fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; - } - - if($code != 250 && $code != 251) { - $this->error = - array("error" => "VRFY failed on name '$name'", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . - ": " . $rply . $this->CRLF; - } - return false; - } - return $rply; - } - - /******************************************************************* - * INTERNAL FUNCTIONS * - ******************************************************************/ - - /** - * Read in as many lines as possible - * either before eof or socket timeout occurs on the operation. - * With SMTP we can tell if we have more lines to read if the - * 4th character is '-' symbol. If it is a space then we don't - * need to read anything else. - * @access private - * @return string - */ - function get_lines() { - $data = ""; - while($str = @fgets($this->smtp_conn,515)) { - if($this->do_debug >= 4) { - echo "SMTP -> get_lines(): \$data was \"$data\"" . - $this->CRLF; - echo "SMTP -> get_lines(): \$str is \"$str\"" . - $this->CRLF; - } - $data .= $str; - if($this->do_debug >= 4) { - echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF; - } - # if the 4th character is a space then we are done reading - # so just break the loop - if(substr($str,3,1) == " ") { break; } - } - return $data; - } - -} - - - ?> diff --git a/libs/phpmailer/index.html b/libs/phpmailer/index.html deleted file mode 100644 index 2efb97f31..000000000 --- a/libs/phpmailer/index.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/libs/phpmailer/language/index.html b/libs/phpmailer/language/index.html deleted file mode 100644 index 2efb97f31..000000000 --- a/libs/phpmailer/language/index.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/libs/phpmailer/language/phpmailer.lang-en.php b/libs/phpmailer/language/phpmailer.lang-en.php deleted file mode 100644 index 34b692316..000000000 --- a/libs/phpmailer/language/phpmailer.lang-en.php +++ /dev/null @@ -1,23 +0,0 @@ -exceptions = ($exceptions == true); - } - - /** - * Sets message type to HTML. - * @param bool $ishtml - * @return void - */ - public function IsHTML($ishtml = true) { - if ($ishtml) { - $this->ContentType = 'text/html'; - } else { - $this->ContentType = 'text/plain'; - } - } - - /** - * Sets Mailer to send message using SMTP. - * @return void - */ - public function IsSMTP() { - $this->Mailer = 'smtp'; - } - - /** - * Sets Mailer to send message using PHP mail() function. - * @return void - */ - public function IsMail() { - $this->Mailer = 'mail'; - } - - /** - * Sets Mailer to send message using the $Sendmail program. - * @return void - */ - public function IsSendmail() { - if (!stristr(ini_get('sendmail_path'), 'sendmail')) { - $this->Sendmail = '/var/qmail/bin/sendmail'; - } - $this->Mailer = 'sendmail'; - } - - /** - * Sets Mailer to send message using the qmail MTA. - * @return void - */ - public function IsQmail() { - if (stristr(ini_get('sendmail_path'), 'qmail')) { - $this->Sendmail = '/var/qmail/bin/sendmail'; - } - $this->Mailer = 'sendmail'; - } - - ///////////////////////////////////////////////// - // METHODS, RECIPIENTS - ///////////////////////////////////////////////// - - /** - * Adds a "To" address. - * @param string $address - * @param string $name - * @return boolean true on success, false if address already used - */ - public function AddAddress($address, $name = '') { - return $this->AddAnAddress('to', $address, $name); - } - - /** - * Adds a "Cc" address. - * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer. - * @param string $address - * @param string $name - * @return boolean true on success, false if address already used - */ - public function AddCC($address, $name = '') { - return $this->AddAnAddress('cc', $address, $name); - } - - /** - * Adds a "Bcc" address. - * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer. - * @param string $address - * @param string $name - * @return boolean true on success, false if address already used - */ - public function AddBCC($address, $name = '') { - return $this->AddAnAddress('bcc', $address, $name); - } - - /** - * Adds a "Reply-to" address. - * @param string $address - * @param string $name - * @return boolean - */ - public function AddReplyTo($address, $name = '') { - return $this->AddAnAddress('ReplyTo', $address, $name); - } - - /** - * Adds an address to one of the recipient arrays - * Addresses that have been added already return false, but do not throw exceptions - * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo' - * @param string $address The email address to send to - * @param string $name - * @return boolean true on success, false if address already used or invalid in some way - * @access private - */ - private function AddAnAddress($kind, $address, $name = '') { - if (!preg_match('/^(to|cc|bcc|ReplyTo)$/', $kind)) { - echo 'Invalid recipient array: ' . kind; - return false; - } - $address = trim($address); - $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim - if (!self::ValidateAddress($address)) { - $this->SetError($this->Lang('invalid_address').': '. $address); - if ($this->exceptions) { - throw new phpmailerException($this->Lang('invalid_address').': '.$address); - } - echo $this->Lang('invalid_address').': '.$address; - return false; - } - if ($kind != 'ReplyTo') { - if (!isset($this->all_recipients[strtolower($address)])) { - array_push($this->$kind, array($address, $name)); - $this->all_recipients[strtolower($address)] = true; - return true; - } - } else { - if (!array_key_exists(strtolower($address), $this->ReplyTo)) { - $this->ReplyTo[strtolower($address)] = array($address, $name); - return true; - } - } - return false; -} - -/** - * Set the From and FromName properties - * @param string $address - * @param string $name - * @return boolean - */ - public function SetFrom($address, $name = '',$auto=1) { - $address = trim($address); - $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim - if (!self::ValidateAddress($address)) { - $this->SetError($this->Lang('invalid_address').': '. $address); - if ($this->exceptions) { - throw new phpmailerException($this->Lang('invalid_address').': '.$address); - } - echo $this->Lang('invalid_address').': '.$address; - return false; - } - $this->From = $address; - $this->FromName = $name; - if ($auto) { - if (empty($this->ReplyTo)) { - $this->AddAnAddress('ReplyTo', $address, $name); - } - if (empty($this->Sender)) { - $this->Sender = $address; - } - } - return true; - } - - /** - * Check that a string looks roughly like an email address should - * Static so it can be used without instantiation - * Tries to use PHP built-in validator in the filter extension (from PHP 5.2), falls back to a reasonably competent regex validator - * Conforms approximately to RFC2822 - * @link http://www.hexillion.com/samples/#Regex Original pattern found here - * @param string $address The email address to check - * @return boolean - * @static - * @access public - */ - public static function ValidateAddress($address) { - if (function_exists('filter_var')) { //Introduced in PHP 5.2 - if(filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) { - return false; - } else { - return true; - } - } else { - return preg_match('/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!\.)){0,61}[a-zA-Z0-9_-]?\.)+[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!$)){0,61}[a-zA-Z0-9_]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/', $address); - } - } - - ///////////////////////////////////////////////// - // METHODS, MAIL SENDING - ///////////////////////////////////////////////// - - /** - * Creates message and assigns Mailer. If the message is - * not sent successfully then it returns false. Use the ErrorInfo - * variable to view description of the error. - * @return bool - */ - public function Send() { - try { - if((count($this->to) + count($this->cc) + count($this->bcc)) < 1) { - throw new phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL); - } - - // Set whether the message is multipart/alternative - if(!empty($this->AltBody)) { - $this->ContentType = 'multipart/alternative'; - } - - $this->error_count = 0; // reset errors - $this->SetMessageType(); - $header = $this->CreateHeader(); - $body = $this->CreateBody(); - - if (empty($this->Body)) { - throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL); - } - - // digitally sign with DKIM if enabled - if ($this->DKIM_domain && $this->DKIM_private) { - $header_dkim = $this->DKIM_Add($header,$this->Subject,$body); - $header = str_replace("\r\n","\n",$header_dkim) . $header; - } - - // Choose the mailer and send through it - switch($this->Mailer) { - case 'sendmail': - return $this->SendmailSend($header, $body); - case 'smtp': - return $this->SmtpSend($header, $body); - default: - return $this->MailSend($header, $body); - } - - } catch (phpmailerException $e) { - $this->SetError($e->getMessage()); - if ($this->exceptions) { - throw $e; - } - echo $e->getMessage()."\n"; - return false; - } - } - - /** - * Sends mail using the $Sendmail program. - * @param string $header The message headers - * @param string $body The message body - * @access protected - * @return bool - */ - protected function SendmailSend($header, $body) { - if ($this->Sender != '') { - $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); - } else { - $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail)); - } - if ($this->SingleTo === true) { - foreach ($this->SingleToArray as $key => $val) { - if(!@$mail = popen($sendmail, 'w')) { - throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); - } - fputs($mail, "To: " . $val . "\n"); - fputs($mail, $header); - fputs($mail, $body); - $result = pclose($mail); - // implement call back function if it exists - $isSent = ($result == 0) ? 1 : 0; - $this->doCallback($isSent,$val,$this->cc,$this->bcc,$this->Subject,$body); - if($result != 0) { - throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); - } - } - } else { - if(!@$mail = popen($sendmail, 'w')) { - throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); - } - fputs($mail, $header); - fputs($mail, $body); - $result = pclose($mail); - // implement call back function if it exists - $isSent = ($result == 0) ? 1 : 0; - $this->doCallback($isSent,$this->to,$this->cc,$this->bcc,$this->Subject,$body); - if($result != 0) { - throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); - } - } - return true; - } - - /** - * Sends mail using the PHP mail() function. - * @param string $header The message headers - * @param string $body The message body - * @access protected - * @return bool - */ - protected function MailSend($header, $body) { - $toArr = array(); - foreach($this->to as $t) { - $toArr[] = $this->AddrFormat($t); - } - $to = implode(', ', $toArr); - - $params = sprintf("-oi -f %s", $this->Sender); - if ($this->Sender != '' && strlen(ini_get('safe_mode'))< 1) { - $old_from = ini_get('sendmail_from'); - ini_set('sendmail_from', $this->Sender); - if ($this->SingleTo === true && count($toArr) > 1) { - foreach ($toArr as $key => $val) { - $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); - // implement call back function if it exists - $isSent = ($rt == 1) ? 1 : 0; - $this->doCallback($isSent,$val,$this->cc,$this->bcc,$this->Subject,$body); - } - } else { - $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); - // implement call back function if it exists - $isSent = ($rt == 1) ? 1 : 0; - $this->doCallback($isSent,$to,$this->cc,$this->bcc,$this->Subject,$body); - } - } else { - if ($this->SingleTo === true && count($toArr) > 1) { - foreach ($toArr as $key => $val) { - $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); - // implement call back function if it exists - $isSent = ($rt == 1) ? 1 : 0; - $this->doCallback($isSent,$val,$this->cc,$this->bcc,$this->Subject,$body); - } - } else { - $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header); - // implement call back function if it exists - $isSent = ($rt == 1) ? 1 : 0; - $this->doCallback($isSent,$to,$this->cc,$this->bcc,$this->Subject,$body); - } - } - if (isset($old_from)) { - ini_set('sendmail_from', $old_from); - } - if(!$rt) { - throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL); - } - return true; - } - - /** - * Sends mail via SMTP using PhpSMTP - * Returns false if there is a bad MAIL FROM, RCPT, or DATA input. - * @param string $header The message headers - * @param string $body The message body - * @uses SMTP - * @access protected - * @return bool - */ - protected function SmtpSend($header, $body) { - require_once $this->PluginDir . 'smtp.php'; - $bad_rcpt = array(); - - if(!$this->SmtpConnect()) { - throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL); - } - $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender; - if(!$this->smtp->Mail($smtp_from)) { - throw new phpmailerException($this->Lang('from_failed') . $smtp_from, self::STOP_CRITICAL); - } - - // Attempt to send attach all recipients - foreach($this->to as $to) { - if (!$this->smtp->Recipient($to[0])) { - $bad_rcpt[] = $to[0]; - // implement call back function if it exists - $isSent = 0; - $this->doCallback($isSent,$to[0],'','',$this->Subject,$body); - } else { - // implement call back function if it exists - $isSent = 1; - $this->doCallback($isSent,$to[0],'','',$this->Subject,$body); - } - } - foreach($this->cc as $cc) { - if (!$this->smtp->Recipient($cc[0])) { - $bad_rcpt[] = $cc[0]; - // implement call back function if it exists - $isSent = 0; - $this->doCallback($isSent,'',$cc[0],'',$this->Subject,$body); - } else { - // implement call back function if it exists - $isSent = 1; - $this->doCallback($isSent,'',$cc[0],'',$this->Subject,$body); - } - } - foreach($this->bcc as $bcc) { - if (!$this->smtp->Recipient($bcc[0])) { - $bad_rcpt[] = $bcc[0]; - // implement call back function if it exists - $isSent = 0; - $this->doCallback($isSent,'','',$bcc[0],$this->Subject,$body); - } else { - // implement call back function if it exists - $isSent = 1; - $this->doCallback($isSent,'','',$bcc[0],$this->Subject,$body); - } - } - - - if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses - $badaddresses = implode(', ', $bad_rcpt); - throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses); - } - if(!$this->smtp->Data($header . $body)) { - throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL); - } - if($this->SMTPKeepAlive == true) { - $this->smtp->Reset(); - } - return true; - } - - /** - * Initiates a connection to an SMTP server. - * Returns false if the operation failed. - * @uses SMTP - * @access public - * @return bool - */ - public function SmtpConnect() { - if(is_null($this->smtp)) { - $this->smtp = new SMTP(); - } - - $this->smtp->do_debug = $this->SMTPDebug; - $hosts = explode(';', $this->Host); - $index = 0; - $connection = $this->smtp->Connected(); - - // Retry while there is no connection - try { - while($index < count($hosts) && !$connection) { - $hostinfo = array(); - if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) { - $host = $hostinfo[1]; - $port = $hostinfo[2]; - } else { - $host = $hosts[$index]; - $port = $this->Port; - } - - $tls = ($this->SMTPSecure == 'tls'); - $ssl = ($this->SMTPSecure == 'ssl'); - - if($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) { - - $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname()); - $this->smtp->Hello($hello); - - if($tls) { - if(!$this->smtp->StartTLS()) { - throw new phpmailerException($this->Lang('tls')); - } - - //We must resend HELO after tls negotiation - $this->smtp->Hello($hello); - } - - $connection = true; - if($this->SMTPAuth) { - if(!$this->smtp->Authenticate($this->Username, $this->Password)) { - throw new phpmailerException($this->Lang('authenticate')); - } - } - } - $index++; - if(!$connection) { - throw new phpmailerException($this->Lang('connect_host')); - } - } - } catch (phpmailerException $e) { - $this->smtp->Reset(); - throw $e; - } - return true; - } - - /** - * Closes the active SMTP session if one exists. - * @return void - */ - public function SmtpClose() { - if(!is_null($this->smtp)) { - if($this->smtp->Connected()) { - $this->smtp->Quit(); - $this->smtp->Close(); - } - } - } - - /** - * Sets the language for all class error messages. - * Returns false if it cannot load the language file. The default language is English. - * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br") - * @param string $lang_path Path to the language file directory - * @access public - */ - function SetLanguage($langcode = 'en', $lang_path = 'language/') { - //Define full set of translatable strings - $PHPMAILER_LANG = array( - 'provide_address' => 'You must provide at least one recipient email address.', - 'mailer_not_supported' => ' mailer is not supported.', - 'execute' => 'Could not execute: ', - 'instantiate' => 'Could not instantiate mail function.', - 'authenticate' => 'SMTP Error: Could not authenticate.', - 'from_failed' => 'The following From address failed: ', - 'recipients_failed' => 'SMTP Error: The following recipients failed: ', - 'data_not_accepted' => 'SMTP Error: Data not accepted.', - 'connect_host' => 'SMTP Error: Could not connect to SMTP host.', - 'file_access' => 'Could not access file: ', - 'file_open' => 'File Error: Could not open file: ', - 'encoding' => 'Unknown encoding: ', - 'signing' => 'Signing Error: ', - 'smtp_error' => 'SMTP server error: ', - 'empty_message' => 'Message body empty', - 'invalid_address' => 'Invalid address', - 'variable_set' => 'Cannot set or reset variable: ' - ); - //Overwrite language-specific strings. This way we'll never have missing translations - no more "language string failed to load"! - $l = true; - if ($langcode != 'en') { //There is no English translation file - $l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php'; - } - $this->language = $PHPMAILER_LANG; - return ($l == true); //Returns false if language not found - } - - /** - * Return the current array of language strings - * @return array - */ - public function GetTranslations() { - return $this->language; - } - - ///////////////////////////////////////////////// - // METHODS, MESSAGE CREATION - ///////////////////////////////////////////////// - - /** - * Creates recipient headers. - * @access public - * @return string - */ - public function AddrAppend($type, $addr) { - $addr_str = $type . ': '; - $addresses = array(); - foreach ($addr as $a) { - $addresses[] = $this->AddrFormat($a); - } - $addr_str .= implode(', ', $addresses); - $addr_str .= $this->LE; - - return $addr_str; - } - - /** - * Formats an address correctly. - * @access public - * @return string - */ - public function AddrFormat($addr) { - if(empty($addr[1])) { - return $this->SecureHeader($addr[0]); - } else { - return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">"; - } - } - - /** - * Wraps message for use with mailers that do not - * automatically perform wrapping and for quoted-printable. - * Original written by philippe. - * @param string $message The message to wrap - * @param integer $length The line length to wrap to - * @param boolean $qp_mode Whether to run in Quoted-Printable mode - * @access public - * @return string - */ - public function WrapText($message, $length, $qp_mode = false) { - $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE; - // If utf-8 encoding is used, we will need to make sure we don't - // split multibyte characters when we wrap - $is_utf8 = (strtolower($this->CharSet) == "utf-8"); - - $message = $this->FixEOL($message); - if (substr($message, -1) == $this->LE) { - $message = substr($message, 0, -1); - } - - $line = explode($this->LE, $message); - $message = ''; - for ($i=0 ;$i < count($line); $i++) { - $line_part = explode(' ', $line[$i]); - $buf = ''; - for ($e = 0; $e $length)) { - $space_left = $length - strlen($buf) - 1; - if ($e != 0) { - if ($space_left > 20) { - $len = $space_left; - if ($is_utf8) { - $len = $this->UTF8CharBoundary($word, $len); - } elseif (substr($word, $len - 1, 1) == "=") { - $len--; - } elseif (substr($word, $len - 2, 1) == "=") { - $len -= 2; - } - $part = substr($word, 0, $len); - $word = substr($word, $len); - $buf .= ' ' . $part; - $message .= $buf . sprintf("=%s", $this->LE); - } else { - $message .= $buf . $soft_break; - } - $buf = ''; - } - while (strlen($word) > 0) { - $len = $length; - if ($is_utf8) { - $len = $this->UTF8CharBoundary($word, $len); - } elseif (substr($word, $len - 1, 1) == "=") { - $len--; - } elseif (substr($word, $len - 2, 1) == "=") { - $len -= 2; - } - $part = substr($word, 0, $len); - $word = substr($word, $len); - - if (strlen($word) > 0) { - $message .= $part . sprintf("=%s", $this->LE); - } else { - $buf = $part; - } - } - } else { - $buf_o = $buf; - $buf .= ($e == 0) ? $word : (' ' . $word); - - if (strlen($buf) > $length and $buf_o != '') { - $message .= $buf_o . $soft_break; - $buf = $word; - } - } - } - $message .= $buf . $this->LE; - } - - return $message; - } - - /** - * Finds last character boundary prior to maxLength in a utf-8 - * quoted (printable) encoded string. - * Original written by Colin Brown. - * @access public - * @param string $encodedText utf-8 QP text - * @param int $maxLength find last character boundary prior to this length - * @return int - */ - public function UTF8CharBoundary($encodedText, $maxLength) { - $foundSplitPos = false; - $lookBack = 3; - while (!$foundSplitPos) { - $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack); - $encodedCharPos = strpos($lastChunk, "="); - if ($encodedCharPos !== false) { - // Found start of encoded character byte within $lookBack block. - // Check the encoded byte value (the 2 chars after the '=') - $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2); - $dec = hexdec($hex); - if ($dec < 128) { // Single byte character. - // If the encoded char was found at pos 0, it will fit - // otherwise reduce maxLength to start of the encoded char - $maxLength = ($encodedCharPos == 0) ? $maxLength : - $maxLength - ($lookBack - $encodedCharPos); - $foundSplitPos = true; - } elseif ($dec >= 192) { // First byte of a multi byte character - // Reduce maxLength to split at start of character - $maxLength = $maxLength - ($lookBack - $encodedCharPos); - $foundSplitPos = true; - } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back - $lookBack += 3; - } - } else { - // No encoded character found - $foundSplitPos = true; - } - } - return $maxLength; - } - - - /** - * Set the body wrapping. - * @access public - * @return void - */ - public function SetWordWrap() { - if($this->WordWrap < 1) { - return; - } - - switch($this->message_type) { - case 'alt': - case 'alt_attachments': - $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap); - break; - default: - $this->Body = $this->WrapText($this->Body, $this->WordWrap); - break; - } - } - - /** - * Assembles message header. - * @access public - * @return string The assembled header - */ - public function CreateHeader() { - $result = ''; - - // Set the boundaries - $uniq_id = md5(uniqid(time())); - $this->boundary[1] = 'b1_' . $uniq_id; - $this->boundary[2] = 'b2_' . $uniq_id; - - $result .= $this->HeaderLine('Date', self::RFCDate()); - if($this->Sender == '') { - $result .= $this->HeaderLine('Return-Path', trim($this->From)); - } else { - $result .= $this->HeaderLine('Return-Path', trim($this->Sender)); - } - - // To be created automatically by mail() - if($this->Mailer != 'mail') { - if ($this->SingleTo === true) { - foreach($this->to as $t) { - $this->SingleToArray[] = $this->AddrFormat($t); - } - } else { - if(count($this->to) > 0) { - $result .= $this->AddrAppend('To', $this->to); - } elseif (count($this->cc) == 0) { - $result .= $this->HeaderLine('To', 'undisclosed-recipients:;'); - } - } - } - - $from = array(); - $from[0][0] = trim($this->From); - $from[0][1] = $this->FromName; - $result .= $this->AddrAppend('From', $from); - - // sendmail and mail() extract Cc from the header before sending - if(count($this->cc) > 0) { - $result .= $this->AddrAppend('Cc', $this->cc); - } - - // sendmail and mail() extract Bcc from the header before sending - if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) { - $result .= $this->AddrAppend('Bcc', $this->bcc); - } - - if(count($this->ReplyTo) > 0) { - $result .= $this->AddrAppend('Reply-to', $this->ReplyTo); - } - - // mail() sets the subject itself - if($this->Mailer != 'mail') { - $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject))); - } - - if($this->MessageID != '') { - $result .= $this->HeaderLine('Message-ID',$this->MessageID); - } else { - $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE); - } - $result .= $this->HeaderLine('X-Priority', $this->Priority); - $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (phpmailer.sourceforge.net)'); - - if($this->ConfirmReadingTo != '') { - $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>'); - } - - // Add custom headers - for($index = 0; $index < count($this->CustomHeader); $index++) { - $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1]))); - } - if (!$this->sign_key_file) { - $result .= $this->HeaderLine('MIME-Version', '1.0'); - $result .= $this->GetMailMIME(); - } - - return $result; - } - - /** - * Returns the message MIME. - * @access public - * @return string - */ - public function GetMailMIME() { - $result = ''; - switch($this->message_type) { - case 'plain': - $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding); - $result .= sprintf("Content-Type: %s; charset=\"%s\"", $this->ContentType, $this->CharSet); - break; - case 'attachments': - case 'alt_attachments': - if($this->InlineImageExists()){ - $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE); - } else { - $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;'); - $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); - } - break; - case 'alt': - $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;'); - $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); - break; - } - - if($this->Mailer != 'mail') { - $result .= $this->LE.$this->LE; - } - - return $result; - } - - /** - * Assembles the message body. Returns an empty string on failure. - * @access public - * @return string The assembled message body - */ - public function CreateBody() { - $body = ''; - - if ($this->sign_key_file) { - $body .= $this->GetMailMIME(); - } - - $this->SetWordWrap(); - - switch($this->message_type) { - case 'alt': - $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', ''); - $body .= $this->EncodeString($this->AltBody, $this->Encoding); - $body .= $this->LE.$this->LE; - $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', ''); - $body .= $this->EncodeString($this->Body, $this->Encoding); - $body .= $this->LE.$this->LE; - $body .= $this->EndBoundary($this->boundary[1]); - break; - case 'plain': - $body .= $this->EncodeString($this->Body, $this->Encoding); - break; - case 'attachments': - $body .= $this->GetBoundary($this->boundary[1], '', '', ''); - $body .= $this->EncodeString($this->Body, $this->Encoding); - $body .= $this->LE; - $body .= $this->AttachAll(); - break; - case 'alt_attachments': - $body .= sprintf("--%s%s", $this->boundary[1], $this->LE); - $body .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE); - $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body - $body .= $this->EncodeString($this->AltBody, $this->Encoding); - $body .= $this->LE.$this->LE; - $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body - $body .= $this->EncodeString($this->Body, $this->Encoding); - $body .= $this->LE.$this->LE; - $body .= $this->EndBoundary($this->boundary[2]); - $body .= $this->AttachAll(); - break; - } - - if($this->IsError()) { - $body = ''; - } else if ($this->sign_key_file) { - try { - $file = tempnam('', 'mail'); - file_put_contents($file, $body, LOCK_EX); //TODO check this worked - $signed = tempnam("", "signed"); - if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) { - @unlink($file); - @unlink($signed); - $body = file_get_contents($signed); - } else { - @unlink($file); - @unlink($signed); - throw new phpmailerException($this->Lang("signing").openssl_error_string()); - } - } catch (phpmailerException $e) { - $body = ''; - if ($this->exceptions) { - throw $e; - } - } - } - - return $body; - } - - /** - * Returns the start of a message boundary. - * @access private - */ - private function GetBoundary($boundary, $charSet, $contentType, $encoding) { - $result = ''; - if($charSet == '') { - $charSet = $this->CharSet; - } - if($contentType == '') { - $contentType = $this->ContentType; - } - if($encoding == '') { - $encoding = $this->Encoding; - } - $result .= $this->TextLine('--' . $boundary); - $result .= sprintf("Content-Type: %s; charset = \"%s\"", $contentType, $charSet); - $result .= $this->LE; - $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding); - $result .= $this->LE; - - return $result; - } - - /** - * Returns the end of a message boundary. - * @access private - */ - private function EndBoundary($boundary) { - return $this->LE . '--' . $boundary . '--' . $this->LE; - } - - /** - * Sets the message type. - * @access private - * @return void - */ - private function SetMessageType() { - if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) { - $this->message_type = 'plain'; - } else { - if(count($this->attachment) > 0) { - $this->message_type = 'attachments'; - } - if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) { - $this->message_type = 'alt'; - } - if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) { - $this->message_type = 'alt_attachments'; - } - } - } - - /** - * Returns a formatted header line. - * @access public - * @return string - */ - public function HeaderLine($name, $value) { - return $name . ': ' . $value . $this->LE; - } - - /** - * Returns a formatted mail line. - * @access public - * @return string - */ - public function TextLine($value) { - return $value . $this->LE; - } - - ///////////////////////////////////////////////// - // CLASS METHODS, ATTACHMENTS - ///////////////////////////////////////////////// - - /** - * Adds an attachment from a path on the filesystem. - * Returns false if the file could not be found - * or accessed. - * @param string $path Path to the attachment. - * @param string $name Overrides the attachment name. - * @param string $encoding File encoding (see $Encoding). - * @param string $type File extension (MIME) type. - * @return bool - */ - public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { - try { - if(!@is_file($path)) { - throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE); - } - $filename = basename($path); - if($name == '') { - $name = $filename; - } - - $this->attachment[] = array( - 0 => $path, - 1 => $filename, - 2 => $name, - 3 => $encoding, - 4 => $type, - 5 => false, // isStringAttachment - 6 => 'attachment', - 7 => 0 - ); - - } catch (phpmailerException $e) { - $this->SetError($e->getMessage()); - if ($this->exceptions) { - throw $e; - } - echo $e->getMessage()."\n"; - if ( $e->getCode() == self::STOP_CRITICAL ) { - return false; - } - } - return true; - } - - /** - * Return the current array of attachments - * @return array - */ - public function GetAttachments() { - return $this->attachment; - } - - /** - * Attaches all fs, string, and binary attachments to the message. - * Returns an empty string on failure. - * @access private - * @return string - */ - private function AttachAll() { - // Return text of body - $mime = array(); - $cidUniq = array(); - $incl = array(); - - // Add all attachments - foreach ($this->attachment as $attachment) { - // Check for string attachment - $bString = $attachment[5]; - if ($bString) { - $string = $attachment[0]; - } else { - $path = $attachment[0]; - } - - if (in_array($attachment[0], $incl)) { continue; } - $filename = $attachment[1]; - $name = $attachment[2]; - $encoding = $attachment[3]; - $type = $attachment[4]; - $disposition = $attachment[6]; - $cid = $attachment[7]; - $incl[] = $attachment[0]; - if ( $disposition == 'inline' && isset($cidUniq[$cid]) ) { continue; } - $cidUniq[$cid] = true; - - $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE); - $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE); - $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE); - - if($disposition == 'inline') { - $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE); - } - - $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE); - - // Encode as string attachment - if($bString) { - $mime[] = $this->EncodeString($string, $encoding); - if($this->IsError()) { - return ''; - } - $mime[] = $this->LE.$this->LE; - } else { - $mime[] = $this->EncodeFile($path, $encoding); - if($this->IsError()) { - return ''; - } - $mime[] = $this->LE.$this->LE; - } - } - - $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE); - - return join('', $mime); - } - - /** - * Encodes attachment in requested format. - * Returns an empty string on failure. - * @param string $path The full path to the file - * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' - * @see EncodeFile() - * @access private - * @return string - */ - private function EncodeFile($path, $encoding = 'base64') { - try { - if (!is_readable($path)) { - throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE); - } - if (function_exists('get_magic_quotes')) { - function get_magic_quotes() { - return false; - } -} - if (PHP_VERSION < 5) { - $magic_quotes = get_magic_quotes_runtime(); - set_magic_quotes_runtime(0); - } - $file_buffer = file_get_contents($path); - $file_buffer = $this->EncodeString($file_buffer, $encoding); - if (PHP_VERSION < 5) { set_magic_quotes_runtime($magic_quotes); } - return $file_buffer; - } catch (Exception $e) { - $this->SetError($e->getMessage()); - return ''; - } - } - - /** - * Encodes string to requested format. - * Returns an empty string on failure. - * @param string $str The text to encode - * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' - * @access public - * @return string - */ - public function EncodeString ($str, $encoding = 'base64') { - $encoded = ''; - switch(strtolower($encoding)) { - case 'base64': - $encoded = chunk_split(base64_encode($str), 76, $this->LE); - break; - case '7bit': - case '8bit': - $encoded = $this->FixEOL($str); - //Make sure it ends with a line break - if (substr($encoded, -(strlen($this->LE))) != $this->LE) - $encoded .= $this->LE; - break; - case 'binary': - $encoded = $str; - break; - case 'quoted-printable': - $encoded = $this->EncodeQP($str); - break; - default: - $this->SetError($this->Lang('encoding') . $encoding); - break; - } - return $encoded; - } - - /** - * Encode a header string to best (shortest) of Q, B, quoted or none. - * @access public - * @return string - */ - public function EncodeHeader ($str, $position = 'text') { - $x = 0; - - switch (strtolower($position)) { - case 'phrase': - if (!preg_match('/[\200-\377]/', $str)) { - // Can't use addslashes as we don't know what value has magic_quotes_sybase - $encoded = addcslashes($str, "\0..\37\177\\\""); - if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) { - return ($encoded); - } else { - return ("\"$encoded\""); - } - } - $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches); - break; - case 'comment': - $x = preg_match_all('/[()"]/', $str, $matches); - // Fall-through - case 'text': - default: - $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches); - break; - } - - if ($x == 0) { - return ($str); - } - - $maxlen = 75 - 7 - strlen($this->CharSet); - // Try to select the encoding which should produce the shortest output - if (strlen($str)/3 < $x) { - $encoding = 'B'; - if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) { - // Use a custom function which correctly encodes and wraps long - // multibyte strings without breaking lines within a character - $encoded = $this->Base64EncodeWrapMB($str); - } else { - $encoded = base64_encode($str); - $maxlen -= $maxlen % 4; - $encoded = trim(chunk_split($encoded, $maxlen, "\n")); - } - } else { - $encoding = 'Q'; - $encoded = $this->EncodeQ($str, $position); - $encoded = $this->WrapText($encoded, $maxlen, true); - $encoded = str_replace('='.$this->LE, "\n", trim($encoded)); - } - - $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded); - $encoded = trim(str_replace("\n", $this->LE, $encoded)); - - return $encoded; - } - - /** - * Checks if a string contains multibyte characters. - * @access public - * @param string $str multi-byte text to wrap encode - * @return bool - */ - public function HasMultiBytes($str) { - if (function_exists('mb_strlen')) { - return (strlen($str) > mb_strlen($str, $this->CharSet)); - } else { // Assume no multibytes (we can't handle without mbstring functions anyway) - return false; - } - } - - /** - * Correctly encodes and wraps long multibyte strings for mail headers - * without breaking lines within a character. - * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php - * @access public - * @param string $str multi-byte text to wrap encode - * @return string - */ - public function Base64EncodeWrapMB($str) { - $start = "=?".$this->CharSet."?B?"; - $end = "?="; - $encoded = ""; - - $mb_length = mb_strlen($str, $this->CharSet); - // Each line must have length <= 75, including $start and $end - $length = 75 - strlen($start) - strlen($end); - // Average multi-byte ratio - $ratio = $mb_length / strlen($str); - // Base64 has a 4:3 ratio - $offset = $avgLength = floor($length * $ratio * .75); - - for ($i = 0; $i < $mb_length; $i += $offset) { - $lookBack = 0; - - do { - $offset = $avgLength - $lookBack; - $chunk = mb_substr($str, $i, $offset, $this->CharSet); - $chunk = base64_encode($chunk); - $lookBack++; - } - while (strlen($chunk) > $length); - - $encoded .= $chunk . $this->LE; - } - - // Chomp the last linefeed - $encoded = substr($encoded, 0, -strlen($this->LE)); - return $encoded; - } - - /** - * Encode string to quoted-printable. - * Only uses standard PHP, slow, but will always work - * @access public - * @param string $string the text to encode - * @param integer $line_max Number of chars allowed on a line before wrapping - * @return string - */ - public function EncodeQPphp( $input = '', $line_max = 76, $space_conv = false) { - $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); - $lines = preg_split('/(?:\r\n|\r|\n)/', $input); - $eol = "\r\n"; - $escape = '='; - $output = ''; - while( list(, $line) = each($lines) ) { - $linlen = strlen($line); - $newline = ''; - for($i = 0; $i < $linlen; $i++) { - $c = substr( $line, $i, 1 ); - $dec = ord( $c ); - if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E - $c = '=2E'; - } - if ( $dec == 32 ) { - if ( $i == ( $linlen - 1 ) ) { // convert space at eol only - $c = '=20'; - } else if ( $space_conv ) { - $c = '=20'; - } - } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required - $h2 = floor($dec/16); - $h1 = floor($dec%16); - $c = $escape.$hex[$h2].$hex[$h1]; - } - if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted - $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay - $newline = ''; - // check if newline first character will be point or not - if ( $dec == 46 ) { - $c = '=2E'; - } - } - $newline .= $c; - } // end of for - $output .= $newline.$eol; - } // end of while - return $output; - } - - /** - * Encode string to RFC2045 (6.7) quoted-printable format - * Uses a PHP5 stream filter to do the encoding about 64x faster than the old version - * Also results in same content as you started with after decoding - * @see EncodeQPphp() - * @access public - * @param string $string the text to encode - * @param integer $line_max Number of chars allowed on a line before wrapping - * @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function - * @return string - * @author Marcus Bointon - */ - public function EncodeQP($string, $line_max = 76, $space_conv = false) { - if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3) - return quoted_printable_encode($string); - } - $filters = stream_get_filters(); - if (!in_array('convert.*', $filters)) { //Got convert stream filter? - return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation - } - $fp = fopen('php://temp/', 'r+'); - $string = preg_replace('/\r\n?/', $this->LE, $string); //Normalise line breaks - $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE); - $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params); - fputs($fp, $string); - rewind($fp); - $out = stream_get_contents($fp); - stream_filter_remove($s); - $out = preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange - fclose($fp); - return $out; - } - - /** - * Encode string to q encoding. - * @link http://tools.ietf.org/html/rfc2047 - * @param string $str the text to encode - * @param string $position Where the text is going to be used, see the RFC for what that means - * @access public - * @return string - */ - public function EncodeQ ($str, $position = 'text') { - // There should not be any EOL in the string - $encoded = preg_replace('/[\r\n]*/', '', $str); - - switch (strtolower($position)) { - case 'phrase': - $encoded = preg_replace_callback('/([^A-Za-z0-9!*+\/ -])/', function($n) { return '='.sprintf('%02X', ord('\\1')); }, $encoded); - break; - case 'comment': - $encoded = preg_replace_callback('/([\(\)\"])/', function($n) { return '='.sprintf('%02X', ord('\\1')); }, $encoded); - case 'text': - default: - // Replace every high ascii, control =, ? and _ characters - //TODO using /e (equivalent to eval()) is probably not a good idea - $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e', - "'='.sprintf('%02X', ord('\\1'))", $encoded); - break; - } - - // Replace every spaces to _ (more readable than =20) - $encoded = str_replace(' ', '_', $encoded); - - return $encoded; - } - - /** - * Adds a string or binary attachment (non-filesystem) to the list. - * This method can be used to attach ascii or binary data, - * such as a BLOB record from a database. - * @param string $string String attachment data. - * @param string $filename Name of the attachment. - * @param string $encoding File encoding (see $Encoding). - * @param string $type File extension (MIME) type. - * @return void - */ - public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') { - // Append to $attachment array - $this->attachment[] = array( - 0 => $string, - 1 => $filename, - 2 => basename($filename), - 3 => $encoding, - 4 => $type, - 5 => true, // isStringAttachment - 6 => 'attachment', - 7 => 0 - ); - } - - /** - * Adds an embedded attachment. This can include images, sounds, and - * just about any other document. Make sure to set the $type to an - * image type. For JPEG images use "image/jpeg" and for GIF images - * use "image/gif". - * @param string $path Path to the attachment. - * @param string $cid Content ID of the attachment. Use this to identify - * the Id for accessing the image in an HTML form. - * @param string $name Overrides the attachment name. - * @param string $encoding File encoding (see $Encoding). - * @param string $type File extension (MIME) type. - * @return bool - */ - public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { - - if(!@is_file($path)) { - $this->SetError($this->Lang('file_access') . $path); - return false; - } - - $filename = basename($path); - if($name == '') { - $name = $filename; - } - - // Append to $attachment array - $this->attachment[] = array( - 0 => $path, - 1 => $filename, - 2 => $name, - 3 => $encoding, - 4 => $type, - 5 => false, // isStringAttachment - 6 => 'inline', - 7 => $cid - ); - - return true; - } - - /** - * Returns true if an inline attachment is present. - * @access public - * @return bool - */ - public function InlineImageExists() { - foreach($this->attachment as $attachment) { - if ($attachment[6] == 'inline') { - return true; - } - } - return false; - } - - ///////////////////////////////////////////////// - // CLASS METHODS, MESSAGE RESET - ///////////////////////////////////////////////// - - /** - * Clears all recipients assigned in the TO array. Returns void. - * @return void - */ - public function ClearAddresses() { - foreach($this->to as $to) { - unset($this->all_recipients[strtolower($to[0])]); - } - $this->to = array(); - } - - /** - * Clears all recipients assigned in the CC array. Returns void. - * @return void - */ - public function ClearCCs() { - foreach($this->cc as $cc) { - unset($this->all_recipients[strtolower($cc[0])]); - } - $this->cc = array(); - } - - /** - * Clears all recipients assigned in the BCC array. Returns void. - * @return void - */ - public function ClearBCCs() { - foreach($this->bcc as $bcc) { - unset($this->all_recipients[strtolower($bcc[0])]); - } - $this->bcc = array(); - } - - /** - * Clears all recipients assigned in the ReplyTo array. Returns void. - * @return void - */ - public function ClearReplyTos() { - $this->ReplyTo = array(); - } - - /** - * Clears all recipients assigned in the TO, CC and BCC - * array. Returns void. - * @return void - */ - public function ClearAllRecipients() { - $this->to = array(); - $this->cc = array(); - $this->bcc = array(); - $this->all_recipients = array(); - } - - /** - * Clears all previously set filesystem, string, and binary - * attachments. Returns void. - * @return void - */ - public function ClearAttachments() { - $this->attachment = array(); - } - - /** - * Clears all custom headers. Returns void. - * @return void - */ - public function ClearCustomHeaders() { - $this->CustomHeader = array(); - } - - ///////////////////////////////////////////////// - // CLASS METHODS, MISCELLANEOUS - ///////////////////////////////////////////////// - - /** - * Adds the error message to the error container. - * @access protected - * @return void - */ - protected function SetError($msg) { - $this->error_count++; - if ($this->Mailer == 'smtp' and !is_null($this->smtp)) { - $lasterror = $this->smtp->getError(); - if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) { - $msg .= '

' . $this->Lang('smtp_error') . $lasterror['smtp_msg'] . "

\n"; - } - } - $this->ErrorInfo = $msg; - } - - /** - * Returns the proper RFC 822 formatted date. - * @access public - * @return string - * @static - */ - public static function RFCDate() { - $tz = date('Z'); - $tzs = ($tz < 0) ? '-' : '+'; - $tz = abs($tz); - $tz = (int)($tz/3600)*100 + ($tz%3600)/60; - $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz); - - return $result; - } - - /** - * Returns the server hostname or 'localhost.localdomain' if unknown. - * @access private - * @return string - */ - private function ServerHostname() { - if (!empty($this->Hostname)) { - $result = $this->Hostname; - } elseif (isset($_SERVER['SERVER_NAME'])) { - $result = $_SERVER['SERVER_NAME']; - } else { - $result = 'localhost.localdomain'; - } - - return $result; - } - - /** - * Returns a message in the appropriate language. - * @access private - * @return string - */ - private function Lang($key) { - if(count($this->language) < 1) { - $this->SetLanguage('en'); // set the default language - } - - if(isset($this->language[$key])) { - return $this->language[$key]; - } else { - return 'Language string failed to load: ' . $key; - } - } - - /** - * Returns true if an error occurred. - * @access public - * @return bool - */ - public function IsError() { - return ($this->error_count > 0); - } - - /** - * Changes every end of line from CR or LF to CRLF. - * @access private - * @return string - */ - private function FixEOL($str) { - $str = str_replace("\r\n", "\n", $str); - $str = str_replace("\r", "\n", $str); - $str = str_replace("\n", $this->LE, $str); - return $str; - } - - /** - * Adds a custom header. - * @access public - * @return void - */ - public function AddCustomHeader($custom_header) { - $this->CustomHeader[] = explode(':', $custom_header, 2); - } - - /** - * Evaluates the message and returns modifications for inline images and backgrounds - * @access public - * @return $message - */ - public function MsgHTML($message,$basedir='') { - preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images); - if(isset($images[2])) { - foreach($images[2] as $i => $url) { - // do not change urls for absolute images (thanks to corvuscorax) - if (!preg_match('#^[A-z]+://#',$url)) { - $filename = basename($url); - $directory = dirname($url); - ($directory == '.')?$directory='':''; - $cid = 'cid:' . md5($filename); - $ext = pathinfo($filename, PATHINFO_EXTENSION); - $mimeType = self::_mime_types($ext); - if ( strlen($basedir) > 1 && substr($basedir,-1) != '/') { $basedir .= '/'; } - if ( strlen($directory) > 1 && substr($directory,-1) != '/') { $directory .= '/'; } - if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64',$mimeType) ) { - $message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message); - } - } - } - } - $this->IsHTML(true); - $this->Body = $message; - $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s','',$message))); - if ( !empty($textMsg) && empty($this->AltBody) ) { - $this->AltBody = html_entity_decode($textMsg); - } - if ( empty($this->AltBody) ) { - $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n"; - } - } - - /** - * Gets the MIME type of the embedded or inline image - * @param string File extension - * @access public - * @return string MIME type of ext - * @static - */ - public static function _mime_types($ext = '') { - $mimes = array( - 'hqx' => 'application/mac-binhex40', - 'cpt' => 'application/mac-compactpro', - 'doc' => 'application/msword', - 'bin' => 'application/macbinary', - 'dms' => 'application/octet-stream', - 'lha' => 'application/octet-stream', - 'lzh' => 'application/octet-stream', - 'exe' => 'application/octet-stream', - 'class' => 'application/octet-stream', - 'psd' => 'application/octet-stream', - 'so' => 'application/octet-stream', - 'sea' => 'application/octet-stream', - 'dll' => 'application/octet-stream', - 'oda' => 'application/oda', - 'pdf' => 'application/pdf', - 'ai' => 'application/postscript', - 'eps' => 'application/postscript', - 'ps' => 'application/postscript', - 'smi' => 'application/smil', - 'smil' => 'application/smil', - 'mif' => 'application/vnd.mif', - 'xls' => 'application/vnd.ms-excel', - 'ppt' => 'application/vnd.ms-powerpoint', - 'wbxml' => 'application/vnd.wap.wbxml', - 'wmlc' => 'application/vnd.wap.wmlc', - 'dcr' => 'application/x-director', - 'dir' => 'application/x-director', - 'dxr' => 'application/x-director', - 'dvi' => 'application/x-dvi', - 'gtar' => 'application/x-gtar', - 'php' => 'application/x-httpd-php', - 'php4' => 'application/x-httpd-php', - 'php3' => 'application/x-httpd-php', - 'phtml' => 'application/x-httpd-php', - 'phps' => 'application/x-httpd-php-source', - 'js' => 'application/x-javascript', - 'swf' => 'application/x-shockwave-flash', - 'sit' => 'application/x-stuffit', - 'tar' => 'application/x-tar', - 'tgz' => 'application/x-tar', - 'xhtml' => 'application/xhtml+xml', - 'xht' => 'application/xhtml+xml', - 'zip' => 'application/zip', - 'mid' => 'audio/midi', - 'midi' => 'audio/midi', - 'mpga' => 'audio/mpeg', - 'mp2' => 'audio/mpeg', - 'mp3' => 'audio/mpeg', - 'aif' => 'audio/x-aiff', - 'aiff' => 'audio/x-aiff', - 'aifc' => 'audio/x-aiff', - 'ram' => 'audio/x-pn-realaudio', - 'rm' => 'audio/x-pn-realaudio', - 'rpm' => 'audio/x-pn-realaudio-plugin', - 'ra' => 'audio/x-realaudio', - 'rv' => 'video/vnd.rn-realvideo', - 'wav' => 'audio/x-wav', - 'bmp' => 'image/bmp', - 'gif' => 'image/gif', - 'jpeg' => 'image/jpeg', - 'jpg' => 'image/jpeg', - 'jpe' => 'image/jpeg', - 'png' => 'image/png', - 'tiff' => 'image/tiff', - 'tif' => 'image/tiff', - 'css' => 'text/css', - 'html' => 'text/html', - 'htm' => 'text/html', - 'shtml' => 'text/html', - 'txt' => 'text/plain', - 'text' => 'text/plain', - 'log' => 'text/plain', - 'rtx' => 'text/richtext', - 'rtf' => 'text/rtf', - 'xml' => 'text/xml', - 'xsl' => 'text/xml', - 'mpeg' => 'video/mpeg', - 'mpg' => 'video/mpeg', - 'mpe' => 'video/mpeg', - 'qt' => 'video/quicktime', - 'mov' => 'video/quicktime', - 'avi' => 'video/x-msvideo', - 'movie' => 'video/x-sgi-movie', - 'doc' => 'application/msword', - 'word' => 'application/msword', - 'xl' => 'application/excel', - 'eml' => 'message/rfc822' - ); - return ( ! isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)]; - } - - /** - * Set (or reset) Class Objects (variables) - * - * Usage Example: - * $page->set('X-Priority', '3'); - * - * @access public - * @param string $name Parameter Name - * @param mixed $value Parameter Value - * NOTE: will not work with arrays, there are no arrays to set/reset - * @todo Should this not be using __set() magic function? - */ - public function set ( $name, $value = '' ) { - try { - if ( isset($this->$name) ) { - $this->$name = $value; - } else { - throw new phpmailerException($this->Lang('variable_set') . $name, self::STOP_CRITICAL); - } - } catch (Exception $e) { - $this->SetError($e->getMessage()); - if ($e->getCode() == self::STOP_CRITICAL) { - return false; - } - } - return true; - } - - /** - * Strips newlines to prevent header injection. - * @access public - * @param string $str String - * @return string - */ - public function SecureHeader($str) { - $str = str_replace("\r", '', $str); - $str = str_replace("\n", '', $str); - return trim($str); - } - - /** - * Set the private key file and password to sign the message. - * - * @access public - * @param string $key_filename Parameter File Name - * @param string $key_pass Password for private key - */ - public function Sign($cert_filename, $key_filename, $key_pass) { - $this->sign_cert_file = $cert_filename; - $this->sign_key_file = $key_filename; - $this->sign_key_pass = $key_pass; - } - - /** - * Set the private key file and password to sign the message. - * - * @access public - * @param string $key_filename Parameter File Name - * @param string $key_pass Password for private key - */ - public function DKIM_QP($txt) { - $tmp=""; - $line=""; - for ($i=0;$iDKIM_private); - if ($this->DKIM_passphrase!='') { - $privKey = openssl_pkey_get_private($privKeyStr,$this->DKIM_passphrase); - } else { - $privKey = $privKeyStr; - } - if (openssl_sign($s, $signature, $privKey)) { - return base64_encode($signature); - } - } - - /** - * Generate DKIM Canonicalization Header - * - * @access public - * @param string $s Header - */ - public function DKIM_HeaderC($s) { - $s=preg_replace("/\r\n\s+/"," ",$s); - $lines=explode("\r\n",$s); - foreach ($lines as $key=>$line) { - list($heading,$value)=explode(":",$line,2); - $heading=strtolower($heading); - $value=preg_replace("/\s+/"," ",$value) ; // Compress useless spaces - $lines[$key]=$heading.":".trim($value) ; // Don't forget to remove WSP around the value - } - $s=implode("\r\n",$lines); - return $s; - } - - /** - * Generate DKIM Canonicalization Body - * - * @access public - * @param string $body Message Body - */ - public function DKIM_BodyC($body) { - if ($body == '') return "\r\n"; - // stabilize line endings - $body=str_replace("\r\n","\n",$body); - $body=str_replace("\n","\r\n",$body); - // END stabilize line endings - while (substr($body,strlen($body)-4,4) == "\r\n\r\n") { - $body=substr($body,0,strlen($body)-2); - } - return $body; - } - - /** - * Create the DKIM header, body, as new header - * - * @access public - * @param string $headers_line Header lines - * @param string $subject Subject - * @param string $body Body - */ - public function DKIM_Add($headers_line,$subject,$body) { - $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms - $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body - $DKIMquery = 'dns/txt'; // Query method - $DKIMtime = time() ; // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone) - $subject_header = "Subject: $subject"; - $headers = explode("\r\n",$headers_line); - foreach($headers as $header) { - if (strpos($header,'From:') === 0) { - $from_header=$header; - } elseif (strpos($header,'To:') === 0) { - $to_header=$header; - } - } - $from = str_replace('|','=7C',$this->DKIM_QP($from_header)); - $to = str_replace('|','=7C',$this->DKIM_QP($to_header)); - $subject = str_replace('|','=7C',$this->DKIM_QP($subject_header)) ; // Copied header fields (dkim-quoted-printable - $body = $this->DKIM_BodyC($body); - $DKIMlen = strlen($body) ; // Length of body - $DKIMb64 = base64_encode(pack("H*", sha1($body))) ; // Base64 of packed binary SHA-1 hash of body - $ident = ($this->DKIM_identity == '')? '' : " i=" . $this->DKIM_identity . ";"; - $dkimhdrs = "DKIM-Signature: v=1; a=" . $DKIMsignatureType . "; q=" . $DKIMquery . "; l=" . $DKIMlen . "; s=" . $this->DKIM_selector . ";\r\n". - "\tt=" . $DKIMtime . "; c=" . $DKIMcanonicalization . ";\r\n". - "\th=From:To:Subject;\r\n". - "\td=" . $this->DKIM_domain . ";" . $ident . "\r\n". - "\tz=$from\r\n". - "\t|$to\r\n". - "\t|$subject;\r\n". - "\tbh=" . $DKIMb64 . ";\r\n". - "\tb="; - $toSign = $this->DKIM_HeaderC($from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs); - $signed = $this->DKIM_Sign($toSign); - return "X-PHPMAILER-DKIM: phpmailer.worxware.com\r\n".$dkimhdrs.$signed."\r\n"; - } - - protected function doCallback($isSent,$to,$cc,$bcc,$subject,$body) { - if (!empty($this->action_function) && function_exists($this->action_function)) { - $params = array($isSent,$to,$cc,$bcc,$subject,$body); - call_user_func_array($this->action_function,$params); - } - } -} - -class phpmailerException extends Exception { - public function errorMessage() { - $errorMsg = '' . $this->getMessage() . "
\n"; - return $errorMsg; - } -} -?> \ No newline at end of file diff --git a/libs/phpmailer/smtp.php b/libs/phpmailer/smtp.php deleted file mode 100644 index 6f0553273..000000000 --- a/libs/phpmailer/smtp.php +++ /dev/null @@ -1,815 +0,0 @@ -smtp_conn = 0; - $this->error = null; - $this->helo_rply = null; - - $this->do_debug = 0; - } - - ///////////////////////////////////////////////// - // CONNECTION FUNCTIONS - ///////////////////////////////////////////////// - - /** - * Connect to the server specified on the port specified. - * If the port is not specified use the default SMTP_PORT. - * If tval is specified then a connection will try and be - * established with the server for that number of seconds. - * If tval is not specified the default is 30 seconds to - * try on the connection. - * - * SMTP CODE SUCCESS: 220 - * SMTP CODE FAILURE: 421 - * @access public - * @return bool - */ - public function Connect($host,$port=0,$tval=30) { - // set the error val to null so there is no confusion - $this->error = null; - - // make sure we are __not__ connected - if($this->connected()) { - // already connected, generate error - $this->error = array("error" => "Already connected to a server"); - return false; - } - - if(empty($port)) { - $port = $this->SMTP_PORT; - } - - // connect to the smtp server - $this->smtp_conn = @fsockopen($host, // the host of the server - $port, // the port to use - $errno, // error number if any - $errstr, // error message if any - $tval); // give up after ? secs - // verify we connected properly - if(empty($this->smtp_conn)) { - $this->error = array("error" => "Failed to connect to server", - "errno" => $errno, - "errstr" => $errstr); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '
'; - } - return false; - } - - // SMTP server can take longer to respond, give longer timeout for first read - // Windows does not have support for this timeout function - if(substr(PHP_OS, 0, 3) != "WIN") - socket_set_timeout($this->smtp_conn, $tval, 0); - - // get any announcement - $announce = $this->get_lines(); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '
'; - } - - return true; - } - - /** - * Initiate a TLS communication with the server. - * - * SMTP CODE 220 Ready to start TLS - * SMTP CODE 501 Syntax error (no parameters allowed) - * SMTP CODE 454 TLS not available due to temporary reason - * @access public - * @return bool success - */ - public function StartTLS() { - $this->error = null; # to avoid confusion - - if(!$this->connected()) { - $this->error = array("error" => "Called StartTLS() without being connected"); - return false; - } - - fputs($this->smtp_conn,"STARTTLS" . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; - } - - if($code != 220) { - $this->error = - array("error" => "STARTTLS not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; - } - return false; - } - - //Begin encrypted connection - if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { - return false; - } - - return true; - } - - /** - * Performs SMTP authentication. Must be run after running the - * Hello() method. Returns true if successfully authenticated. - * @access public - * @return bool - */ - public function Authenticate($username, $password) { - // Start authentication - fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($code != 334) { - $this->error = - array("error" => "AUTH not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; - } - return false; - } - - // Send encoded username - fputs($this->smtp_conn, base64_encode($username) . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($code != 334) { - $this->error = - array("error" => "Username not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; - } - return false; - } - - // Send encoded password - fputs($this->smtp_conn, base64_encode($password) . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($code != 235) { - $this->error = - array("error" => "Password not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; - } - return false; - } - - return true; - } - - /** - * Returns true if connected to a server otherwise false - * @access public - * @return bool - */ - public function Connected() { - if(!empty($this->smtp_conn)) { - $sock_status = socket_get_status($this->smtp_conn); - if($sock_status["eof"]) { - // the socket is valid but we are not connected - if($this->do_debug >= 1) { - echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected"; - } - $this->Close(); - return false; - } - return true; // everything looks good - } - return false; - } - - /** - * Closes the socket and cleans up the state of the class. - * It is not considered good to use this function without - * first trying to use QUIT. - * @access public - * @return void - */ - public function Close() { - $this->error = null; // so there is no confusion - $this->helo_rply = null; - if(!empty($this->smtp_conn)) { - // close the connection and cleanup - fclose($this->smtp_conn); - $this->smtp_conn = 0; - } - } - - ///////////////////////////////////////////////// - // SMTP COMMANDS - ///////////////////////////////////////////////// - - /** - * Issues a data command and sends the msg_data to the server - * finializing the mail transaction. $msg_data is the message - * that is to be send with the headers. Each header needs to be - * on a single line followed by a with the message headers - * and the message body being seperated by and additional . - * - * Implements rfc 821: DATA - * - * SMTP CODE INTERMEDIATE: 354 - * [data] - * . - * SMTP CODE SUCCESS: 250 - * SMTP CODE FAILURE: 552,554,451,452 - * SMTP CODE FAILURE: 451,554 - * SMTP CODE ERROR : 500,501,503,421 - * @access public - * @return bool - */ - public function Data($msg_data) { - $this->error = null; // so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Data() without being connected"); - return false; - } - - fputs($this->smtp_conn,"DATA" . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; - } - - if($code != 354) { - $this->error = - array("error" => "DATA command not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; - } - return false; - } - - /* the server is ready to accept data! - * according to rfc 821 we should not send more than 1000 - * including the CRLF - * characters on a single line so we will break the data up - * into lines by \r and/or \n then if needed we will break - * each of those into smaller lines to fit within the limit. - * in addition we will be looking for lines that start with - * a period '.' and append and additional period '.' to that - * line. NOTE: this does not count towards limit. - */ - - // normalize the line breaks so we know the explode works - $msg_data = str_replace("\r\n","\n",$msg_data); - $msg_data = str_replace("\r","\n",$msg_data); - $lines = explode("\n",$msg_data); - - /* we need to find a good way to determine is headers are - * in the msg_data or if it is a straight msg body - * currently I am assuming rfc 822 definitions of msg headers - * and if the first field of the first line (':' sperated) - * does not contain a space then it _should_ be a header - * and we can process all lines before a blank "" line as - * headers. - */ - - $field = substr($lines[0],0,strpos($lines[0],":")); - $in_headers = false; - if(!empty($field) && !strstr($field," ")) { - $in_headers = true; - } - - $max_line_length = 998; // used below; set here for ease in change - - while(list(,$line) = @each($lines)) { - $lines_out = null; - if($line == "" && $in_headers) { - $in_headers = false; - } - // ok we need to break this line up into several smaller lines - while(strlen($line) > $max_line_length) { - $pos = strrpos(substr($line,0,$max_line_length)," "); - - // Patch to fix DOS attack - if(!$pos) { - $pos = $max_line_length - 1; - $lines_out[] = substr($line,0,$pos); - $line = substr($line,$pos); - } else { - $lines_out[] = substr($line,0,$pos); - $line = substr($line,$pos + 1); - } - - /* if we are processing headers we need to - * add a LWSP-char to the front of the new line - * rfc 822 on long msg headers - */ - if($in_headers) { - $line = "\t" . $line; - } - } - $lines_out[] = $line; - - // send the lines to the server - while(list(,$line_out) = @each($lines_out)) { - if(strlen($line_out) > 0) - { - if(substr($line_out, 0, 1) == ".") { - $line_out = "." . $line_out; - } - } - fputs($this->smtp_conn,$line_out . $this->CRLF); - } - } - - // message data has been sent - fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; - } - - if($code != 250) { - $this->error = - array("error" => "DATA not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; - } - return false; - } - return true; - } - - /** - * Sends the HELO command to the smtp server. - * This makes sure that we and the server are in - * the same known state. - * - * Implements from rfc 821: HELO - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE ERROR : 500, 501, 504, 421 - * @access public - * @return bool - */ - public function Hello($host = '') { - $this->error = null; // so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Hello() without being connected"); - return false; - } - - // if hostname for HELO was not specified send default - if(empty($host)) { - // determine appropriate default to send to server - $host = "localhost"; - } - - // Send extended hello first (RFC 2821) - if(!$this->SendHello("EHLO", $host)) { - if(!$this->SendHello("HELO", $host)) { - return false; - } - } - - return true; - } - - /** - * Sends a HELO/EHLO command. - * @access private - * @return bool - */ - private function SendHello($hello, $host) { - fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER: " . $rply . $this->CRLF . '
'; - } - - if($code != 250) { - $this->error = - array("error" => $hello . " not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; - } - return false; - } - - $this->helo_rply = $rply; - - return true; - } - - /** - * Starts a mail transaction from the email address specified in - * $from. Returns true if successful or false otherwise. If True - * the mail transaction is started and then one or more Recipient - * commands may be called followed by a Data command. - * - * Implements rfc 821: MAIL FROM: - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE SUCCESS: 552,451,452 - * SMTP CODE SUCCESS: 500,501,421 - * @access public - * @return bool - */ - public function Mail($from) { - $this->error = null; // so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Mail() without being connected"); - return false; - } - - $useVerp = ($this->do_verp ? "XVERP" : ""); - fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; - } - - if($code != 250) { - $this->error = - array("error" => "MAIL not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; - } - return false; - } - return true; - } - - /** - * Sends the quit command to the server and then closes the socket - * if there is no error or the $close_on_error argument is true. - * - * Implements from rfc 821: QUIT - * - * SMTP CODE SUCCESS: 221 - * SMTP CODE ERROR : 500 - * @access public - * @return bool - */ - public function Quit($close_on_error=true) { - $this->error = null; // so there is no confusion - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Quit() without being connected"); - return false; - } - - // send the quit command to the server - fputs($this->smtp_conn,"quit" . $this->CRLF); - - // get any good-bye messages - $byemsg = $this->get_lines(); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '
'; - } - - $rval = true; - $e = null; - - $code = substr($byemsg,0,3); - if($code != 221) { - // use e as a tmp var cause Close will overwrite $this->error - $e = array("error" => "SMTP server rejected quit command", - "smtp_code" => $code, - "smtp_rply" => substr($byemsg,4)); - $rval = false; - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '
'; - } - } - - if(empty($e) || $close_on_error) { - $this->Close(); - } - - return $rval; - } - - /** - * Sends the command RCPT to the SMTP server with the TO: argument of $to. - * Returns true if the recipient was accepted false if it was rejected. - * - * Implements from rfc 821: RCPT TO: - * - * SMTP CODE SUCCESS: 250,251 - * SMTP CODE FAILURE: 550,551,552,553,450,451,452 - * SMTP CODE ERROR : 500,501,503,421 - * @access public - * @return bool - */ - public function Recipient($to) { - $this->error = null; // so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Recipient() without being connected"); - return false; - } - - fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; - } - - if($code != 250 && $code != 251) { - $this->error = - array("error" => "RCPT not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; - } - return false; - } - return true; - } - - /** - * Sends the RSET command to abort and transaction that is - * currently in progress. Returns true if successful false - * otherwise. - * - * Implements rfc 821: RSET - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE ERROR : 500,501,504,421 - * @access public - * @return bool - */ - public function Reset() { - $this->error = null; // so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Reset() without being connected"); - return false; - } - - fputs($this->smtp_conn,"RSET" . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; - } - - if($code != 250) { - $this->error = - array("error" => "RSET failed", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; - } - return false; - } - - return true; - } - - /** - * Starts a mail transaction from the email address specified in - * $from. Returns true if successful or false otherwise. If True - * the mail transaction is started and then one or more Recipient - * commands may be called followed by a Data command. This command - * will send the message to the users terminal if they are logged - * in and send them an email. - * - * Implements rfc 821: SAML FROM: - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE SUCCESS: 552,451,452 - * SMTP CODE SUCCESS: 500,501,502,421 - * @access public - * @return bool - */ - public function SendAndMail($from) { - $this->error = null; // so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called SendAndMail() without being connected"); - return false; - } - - fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; - } - - if($code != 250) { - $this->error = - array("error" => "SAML not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; - } - return false; - } - return true; - } - - /** - * This is an optional command for SMTP that this class does not - * support. This method is here to make the RFC821 Definition - * complete for this class and __may__ be implimented in the future - * - * Implements from rfc 821: TURN - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE FAILURE: 502 - * SMTP CODE ERROR : 500, 503 - * @access public - * @return bool - */ - public function Turn() { - $this->error = array("error" => "This method, TURN, of the SMTP ". - "is not implemented"); - if($this->do_debug >= 1) { - echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '
'; - } - return false; - } - - /** - * Get the current error - * @access public - * @return array - */ - public function getError() { - return $this->error; - } - - ///////////////////////////////////////////////// - // INTERNAL FUNCTIONS - ///////////////////////////////////////////////// - - /** - * Read in as many lines as possible - * either before eof or socket timeout occurs on the operation. - * With SMTP we can tell if we have more lines to read if the - * 4th character is '-' symbol. If it is a space then we don't - * need to read anything else. - * @access private - * @return string - */ - private function get_lines() { - $data = ""; - while($str = @fgets($this->smtp_conn,515)) { - if($this->do_debug >= 4) { - echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '
'; - echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '
'; - } - $data .= $str; - if($this->do_debug >= 4) { - echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '
'; - } - // if 4th character is a space, we are done reading, break the loop - if(substr($str,3,1) == " ") { break; } - } - return $data; - } - -} - -?> \ No newline at end of file