-
+ AD9B3FD9D4DD91BCC2498833FF0EA16889C5EB30095219116604D637C9B5C33E95189AC4DB551ACD678C1AF586E5B9767F61D0898C45E5FDFE30BC1549714020
mp-wp/wp-includes/class-phpmailer.php
(0 . 0)(1 . 1896)
76657 <?php
76658 /*~ class.phpmailer.php
76659 .---------------------------------------------------------------------------.
76660 | Software: PHPMailer - PHP email class |
76661 | Version: 2.0.2 |
76662 | Contact: via sourceforge.net support pages (also www.codeworxtech.com) |
76663 | Info: http://phpmailer.sourceforge.net |
76664 | Support: http://sourceforge.net/projects/phpmailer/ |
76665 | ------------------------------------------------------------------------- |
76666 | Author: Andy Prevost (project admininistrator) |
76667 | Author: Brent R. Matzelle (original founder) |
76668 | Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved. |
76669 | Copyright (c) 2001-2003, Brent R. Matzelle |
76670 | ------------------------------------------------------------------------- |
76671 | License: Distributed under the Lesser General Public License (LGPL) |
76672 | http://www.gnu.org/copyleft/lesser.html |
76673 | This program is distributed in the hope that it will be useful - WITHOUT |
76674 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
76675 | FITNESS FOR A PARTICULAR PURPOSE. |
76676 | ------------------------------------------------------------------------- |
76677 | We offer a number of paid services (www.codeworxtech.com): |
76678 | - Web Hosting on highly optimized fast and secure servers |
76679 | - Technology Consulting |
76680 | - Oursourcing (highly qualified programmers and graphic designers) |
76681 '---------------------------------------------------------------------------'
76682 */
76683 /**
76684 * PHPMailer - PHP email transport class
76685 * @package PHPMailer
76686 * @author Andy Prevost
76687 * @copyright 2004 - 2008 Andy Prevost
76688 */
76689
76690 class PHPMailer {
76691
76692 /////////////////////////////////////////////////
76693 // PROPERTIES, PUBLIC
76694 /////////////////////////////////////////////////
76695
76696 /**
76697 * Email priority (1 = High, 3 = Normal, 5 = low).
76698 * @var int
76699 */
76700 var $Priority = 3;
76701
76702 /**
76703 * Sets the CharSet of the message.
76704 * @var string
76705 */
76706 var $CharSet = 'iso-8859-1';
76707
76708 /**
76709 * Sets the Content-type of the message.
76710 * @var string
76711 */
76712 var $ContentType = 'text/plain';
76713
76714 /**
76715 * Sets the Encoding of the message. Options for this are "8bit",
76716 * "7bit", "binary", "base64", and "quoted-printable".
76717 * @var string
76718 */
76719 var $Encoding = '8bit';
76720
76721 /**
76722 * Holds the most recent mailer error message.
76723 * @var string
76724 */
76725 var $ErrorInfo = '';
76726
76727 /**
76728 * Sets the From email address for the message.
76729 * @var string
76730 */
76731 var $From = 'root@localhost';
76732
76733 /**
76734 * Sets the From name of the message.
76735 * @var string
76736 */
76737 var $FromName = 'Root User';
76738
76739 /**
76740 * Sets the Sender email (Return-Path) of the message. If not empty,
76741 * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
76742 * @var string
76743 */
76744 var $Sender = '';
76745
76746 /**
76747 * Sets the Subject of the message.
76748 * @var string
76749 */
76750 var $Subject = '';
76751
76752 /**
76753 * Sets the Body of the message. This can be either an HTML or text body.
76754 * If HTML then run IsHTML(true).
76755 * @var string
76756 */
76757 var $Body = '';
76758
76759 /**
76760 * Sets the text-only body of the message. This automatically sets the
76761 * email to multipart/alternative. This body can be read by mail
76762 * clients that do not have HTML email capability such as mutt. Clients
76763 * that can read HTML will view the normal Body.
76764 * @var string
76765 */
76766 var $AltBody = '';
76767
76768 /**
76769 * Sets word wrapping on the body of the message to a given number of
76770 * characters.
76771 * @var int
76772 */
76773 var $WordWrap = 0;
76774
76775 /**
76776 * Method to send mail: ("mail", "sendmail", or "smtp").
76777 * @var string
76778 */
76779 var $Mailer = 'mail';
76780
76781 /**
76782 * Sets the path of the sendmail program.
76783 * @var string
76784 */
76785 var $Sendmail = '/usr/sbin/sendmail';
76786
76787 /**
76788 * Path to PHPMailer plugins. This is now only useful if the SMTP class
76789 * is in a different directory than the PHP include path.
76790 * @var string
76791 */
76792 var $PluginDir = '';
76793
76794 /**
76795 * Holds PHPMailer version.
76796 * @var string
76797 */
76798 var $Version = "2.0.2";
76799
76800 /**
76801 * Sets the email address that a reading confirmation will be sent.
76802 * @var string
76803 */
76804 var $ConfirmReadingTo = '';
76805
76806 /**
76807 * Sets the hostname to use in Message-Id and Received headers
76808 * and as default HELO string. If empty, the value returned
76809 * by SERVER_NAME is used or 'localhost.localdomain'.
76810 * @var string
76811 */
76812 var $Hostname = '';
76813
76814 /**
76815 * Sets the message ID to be used in the Message-Id header.
76816 * If empty, a unique id will be generated.
76817 * @var string
76818 */
76819 var $MessageID = '';
76820
76821 /////////////////////////////////////////////////
76822 // PROPERTIES FOR SMTP
76823 /////////////////////////////////////////////////
76824
76825 /**
76826 * Sets the SMTP hosts. All hosts must be separated by a
76827 * semicolon. You can also specify a different port
76828 * for each host by using this format: [hostname:port]
76829 * (e.g. "smtp1.example.com:25;smtp2.example.com").
76830 * Hosts will be tried in order.
76831 * @var string
76832 */
76833 var $Host = 'localhost';
76834
76835 /**
76836 * Sets the default SMTP server port.
76837 * @var int
76838 */
76839 var $Port = 25;
76840
76841 /**
76842 * Sets the SMTP HELO of the message (Default is $Hostname).
76843 * @var string
76844 */
76845 var $Helo = '';
76846
76847 /**
76848 * Sets connection prefix.
76849 * Options are "", "ssl" or "tls"
76850 * @var string
76851 */
76852 var $SMTPSecure = "";
76853
76854 /**
76855 * Sets SMTP authentication. Utilizes the Username and Password variables.
76856 * @var bool
76857 */
76858 var $SMTPAuth = false;
76859
76860 /**
76861 * Sets SMTP username.
76862 * @var string
76863 */
76864 var $Username = '';
76865
76866 /**
76867 * Sets SMTP password.
76868 * @var string
76869 */
76870 var $Password = '';
76871
76872 /**
76873 * Sets the SMTP server timeout in seconds. This function will not
76874 * work with the win32 version.
76875 * @var int
76876 */
76877 var $Timeout = 10;
76878
76879 /**
76880 * Sets SMTP class debugging on or off.
76881 * @var bool
76882 */
76883 var $SMTPDebug = false;
76884
76885 /**
76886 * Prevents the SMTP connection from being closed after each mail
76887 * sending. If this is set to true then to close the connection
76888 * requires an explicit call to SmtpClose().
76889 * @var bool
76890 */
76891 var $SMTPKeepAlive = false;
76892
76893 /**
76894 * Provides the ability to have the TO field process individual
76895 * emails, instead of sending to entire TO addresses
76896 * @var bool
76897 */
76898 var $SingleTo = false;
76899
76900 /////////////////////////////////////////////////
76901 // PROPERTIES, PRIVATE
76902 /////////////////////////////////////////////////
76903
76904 var $smtp = NULL;
76905 var $to = array();
76906 var $cc = array();
76907 var $bcc = array();
76908 var $ReplyTo = array();
76909 var $attachment = array();
76910 var $CustomHeader = array();
76911 var $message_type = '';
76912 var $boundary = array();
76913 var $language = array();
76914 var $error_count = 0;
76915 var $LE = "\n";
76916 var $sign_key_file = "";
76917 var $sign_key_pass = "";
76918
76919 /////////////////////////////////////////////////
76920 // METHODS, VARIABLES
76921 /////////////////////////////////////////////////
76922
76923 /**
76924 * Sets message type to HTML.
76925 * @param bool $bool
76926 * @return void
76927 */
76928 function IsHTML($bool) {
76929 if($bool == true) {
76930 $this->ContentType = 'text/html';
76931 } else {
76932 $this->ContentType = 'text/plain';
76933 }
76934 }
76935
76936 /**
76937 * Sets Mailer to send message using SMTP.
76938 * @return void
76939 */
76940 function IsSMTP() {
76941 $this->Mailer = 'smtp';
76942 }
76943
76944 /**
76945 * Sets Mailer to send message using PHP mail() function.
76946 * @return void
76947 */
76948 function IsMail() {
76949 $this->Mailer = 'mail';
76950 }
76951
76952 /**
76953 * Sets Mailer to send message using the $Sendmail program.
76954 * @return void
76955 */
76956 function IsSendmail() {
76957 $this->Mailer = 'sendmail';
76958 }
76959
76960 /**
76961 * Sets Mailer to send message using the qmail MTA.
76962 * @return void
76963 */
76964 function IsQmail() {
76965 $this->Sendmail = '/var/qmail/bin/sendmail';
76966 $this->Mailer = 'sendmail';
76967 }
76968
76969 /////////////////////////////////////////////////
76970 // METHODS, RECIPIENTS
76971 /////////////////////////////////////////////////
76972
76973 /**
76974 * Adds a "To" address.
76975 * @param string $address
76976 * @param string $name
76977 * @return void
76978 */
76979 function AddAddress($address, $name = '') {
76980 $cur = count($this->to);
76981 $this->to[$cur][0] = trim($address);
76982 $this->to[$cur][1] = $name;
76983 }
76984
76985 /**
76986 * Adds a "Cc" address. Note: this function works
76987 * with the SMTP mailer on win32, not with the "mail"
76988 * mailer.
76989 * @param string $address
76990 * @param string $name
76991 * @return void
76992 */
76993 function AddCC($address, $name = '') {
76994 $cur = count($this->cc);
76995 $this->cc[$cur][0] = trim($address);
76996 $this->cc[$cur][1] = $name;
76997 }
76998
76999 /**
77000 * Adds a "Bcc" address. Note: this function works
77001 * with the SMTP mailer on win32, not with the "mail"
77002 * mailer.
77003 * @param string $address
77004 * @param string $name
77005 * @return void
77006 */
77007 function AddBCC($address, $name = '') {
77008 $cur = count($this->bcc);
77009 $this->bcc[$cur][0] = trim($address);
77010 $this->bcc[$cur][1] = $name;
77011 }
77012
77013 /**
77014 * Adds a "Reply-To" address.
77015 * @param string $address
77016 * @param string $name
77017 * @return void
77018 */
77019 function AddReplyTo($address, $name = '') {
77020 $cur = count($this->ReplyTo);
77021 $this->ReplyTo[$cur][0] = trim($address);
77022 $this->ReplyTo[$cur][1] = $name;
77023 }
77024
77025 /////////////////////////////////////////////////
77026 // METHODS, MAIL SENDING
77027 /////////////////////////////////////////////////
77028
77029 /**
77030 * Creates message and assigns Mailer. If the message is
77031 * not sent successfully then it returns false. Use the ErrorInfo
77032 * variable to view description of the error.
77033 * @return bool
77034 */
77035 function Send() {
77036 $header = '';
77037 $body = '';
77038 $result = true;
77039
77040 if((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
77041 $this->SetError($this->Lang('provide_address'));
77042 return false;
77043 }
77044
77045 /* Set whether the message is multipart/alternative */
77046 if(!empty($this->AltBody)) {
77047 $this->ContentType = 'multipart/alternative';
77048 }
77049
77050 $this->error_count = 0; // reset errors
77051 $this->SetMessageType();
77052 $header .= $this->CreateHeader();
77053 $body = $this->CreateBody();
77054
77055 if($body == '') {
77056 return false;
77057 }
77058
77059 /* Choose the mailer */
77060 switch($this->Mailer) {
77061 case 'sendmail':
77062 $result = $this->SendmailSend($header, $body);
77063 break;
77064 case 'smtp':
77065 $result = $this->SmtpSend($header, $body);
77066 break;
77067 case 'mail':
77068 $result = $this->MailSend($header, $body);
77069 break;
77070 default:
77071 $result = $this->MailSend($header, $body);
77072 break;
77073 //$this->SetError($this->Mailer . $this->Lang('mailer_not_supported'));
77074 //$result = false;
77075 //break;
77076 }
77077
77078 return $result;
77079 }
77080
77081 /**
77082 * Sends mail using the $Sendmail program.
77083 * @access private
77084 * @return bool
77085 */
77086 function SendmailSend($header, $body) {
77087 if ($this->Sender != '') {
77088 $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
77089 } else {
77090 $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
77091 }
77092
77093 if(!@$mail = popen($sendmail, 'w')) {
77094 $this->SetError($this->Lang('execute') . $this->Sendmail);
77095 return false;
77096 }
77097
77098 fputs($mail, $header);
77099 fputs($mail, $body);
77100
77101 $result = pclose($mail);
77102 if (version_compare(phpversion(), '4.2.3') == -1) {
77103 $result = $result >> 8 & 0xFF;
77104 }
77105 if($result != 0) {
77106 $this->SetError($this->Lang('execute') . $this->Sendmail);
77107 return false;
77108 }
77109 return true;
77110 }
77111
77112 /**
77113 * Sends mail using the PHP mail() function.
77114 * @access private
77115 * @return bool
77116 */
77117 function MailSend($header, $body) {
77118
77119 $to = '';
77120 for($i = 0; $i < count($this->to); $i++) {
77121 if($i != 0) { $to .= ', '; }
77122 $to .= $this->AddrFormat($this->to[$i]);
77123 }
77124
77125 $toArr = split(',', $to);
77126
77127 $params = sprintf("-oi -f %s", $this->Sender);
77128 if ($this->Sender != '' && strlen(ini_get('safe_mode')) < 1) {
77129 $old_from = ini_get('sendmail_from');
77130 ini_set('sendmail_from', $this->Sender);
77131 if ($this->SingleTo === true && count($toArr) > 1) {
77132 foreach ($toArr as $key => $val) {
77133 $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
77134 }
77135 } else {
77136 $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
77137 }
77138 } else {
77139 if ($this->SingleTo === true && count($toArr) > 1) {
77140 foreach ($toArr as $key => $val) {
77141 $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
77142 }
77143 } else {
77144 $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header);
77145 }
77146 }
77147
77148 if (isset($old_from)) {
77149 ini_set('sendmail_from', $old_from);
77150 }
77151
77152 if(!$rt) {
77153 $this->SetError($this->Lang('instantiate'));
77154 return false;
77155 }
77156
77157 return true;
77158 }
77159
77160 /**
77161 * Sends mail via SMTP using PhpSMTP (Author:
77162 * Chris Ryan). Returns bool. Returns false if there is a
77163 * bad MAIL FROM, RCPT, or DATA input.
77164 * @access private
77165 * @return bool
77166 */
77167 function SmtpSend($header, $body) {
77168 include_once($this->PluginDir . 'class-smtp.php');
77169 $error = '';
77170 $bad_rcpt = array();
77171
77172 if(!$this->SmtpConnect()) {
77173 return false;
77174 }
77175
77176 $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
77177 if(!$this->smtp->Mail($smtp_from)) {
77178 $error = $this->Lang('from_failed') . $smtp_from;
77179 $this->SetError($error);
77180 $this->smtp->Reset();
77181 return false;
77182 }
77183
77184 /* Attempt to send attach all recipients */
77185 for($i = 0; $i < count($this->to); $i++) {
77186 if(!$this->smtp->Recipient($this->to[$i][0])) {
77187 $bad_rcpt[] = $this->to[$i][0];
77188 }
77189 }
77190 for($i = 0; $i < count($this->cc); $i++) {
77191 if(!$this->smtp->Recipient($this->cc[$i][0])) {
77192 $bad_rcpt[] = $this->cc[$i][0];
77193 }
77194 }
77195 for($i = 0; $i < count($this->bcc); $i++) {
77196 if(!$this->smtp->Recipient($this->bcc[$i][0])) {
77197 $bad_rcpt[] = $this->bcc[$i][0];
77198 }
77199 }
77200
77201 if(count($bad_rcpt) > 0) { // Create error message
77202 for($i = 0; $i < count($bad_rcpt); $i++) {
77203 if($i != 0) {
77204 $error .= ', ';
77205 }
77206 $error .= $bad_rcpt[$i];
77207 }
77208 $error = $this->Lang('recipients_failed') . $error;
77209 $this->SetError($error);
77210 $this->smtp->Reset();
77211 return false;
77212 }
77213
77214 if(!$this->smtp->Data($header . $body)) {
77215 $this->SetError($this->Lang('data_not_accepted'));
77216 $this->smtp->Reset();
77217 return false;
77218 }
77219 if($this->SMTPKeepAlive == true) {
77220 $this->smtp->Reset();
77221 } else {
77222 $this->SmtpClose();
77223 }
77224
77225 return true;
77226 }
77227
77228 /**
77229 * Initiates a connection to an SMTP server. Returns false if the
77230 * operation failed.
77231 * @access private
77232 * @return bool
77233 */
77234 function SmtpConnect() {
77235 if($this->smtp == NULL) {
77236 $this->smtp = new SMTP();
77237 }
77238
77239 $this->smtp->do_debug = $this->SMTPDebug;
77240 $hosts = explode(';', $this->Host);
77241 $index = 0;
77242 $connection = ($this->smtp->Connected());
77243
77244 /* Retry while there is no connection */
77245 while($index < count($hosts) && $connection == false) {
77246 $hostinfo = array();
77247 if(eregi('^(.+):([0-9]+)$', $hosts[$index], $hostinfo)) {
77248 $host = $hostinfo[1];
77249 $port = $hostinfo[2];
77250 } else {
77251 $host = $hosts[$index];
77252 $port = $this->Port;
77253 }
77254
77255 if($this->smtp->Connect(((!empty($this->SMTPSecure))?$this->SMTPSecure.'://':'').$host, $port, $this->Timeout)) {
77256 if ($this->Helo != '') {
77257 $this->smtp->Hello($this->Helo);
77258 } else {
77259 $this->smtp->Hello($this->ServerHostname());
77260 }
77261
77262 $connection = true;
77263 if($this->SMTPAuth) {
77264 if(!$this->smtp->Authenticate($this->Username, $this->Password)) {
77265 $this->SetError($this->Lang('authenticate'));
77266 $this->smtp->Reset();
77267 $connection = false;
77268 }
77269 }
77270 }
77271 $index++;
77272 }
77273 if(!$connection) {
77274 $this->SetError($this->Lang('connect_host'));
77275 }
77276
77277 return $connection;
77278 }
77279
77280 /**
77281 * Closes the active SMTP session if one exists.
77282 * @return void
77283 */
77284 function SmtpClose() {
77285 if($this->smtp != NULL) {
77286 if($this->smtp->Connected()) {
77287 $this->smtp->Quit();
77288 $this->smtp->Close();
77289 }
77290 }
77291 }
77292
77293 /**
77294 * Sets the language for all class error messages. Returns false
77295 * if it cannot load the language file. The default language type
77296 * is English.
77297 * @param string $lang_type Type of language (e.g. Portuguese: "br")
77298 * @param string $lang_path Path to the language file directory
77299 * @access public
77300 * @return bool
77301 */
77302 function SetLanguage($lang_type, $lang_path = 'language/') {
77303 if(file_exists($lang_path.'phpmailer.lang-'.$lang_type.'.php')) {
77304 include($lang_path.'phpmailer.lang-'.$lang_type.'.php');
77305 } elseif (file_exists($lang_path.'phpmailer.lang-en.php')) {
77306 include($lang_path.'phpmailer.lang-en.php');
77307 } else {
77308 $this->SetError('Could not load language file');
77309 return false;
77310 }
77311 $this->language = $PHPMAILER_LANG;
77312
77313 return true;
77314 }
77315
77316 /////////////////////////////////////////////////
77317 // METHODS, MESSAGE CREATION
77318 /////////////////////////////////////////////////
77319
77320 /**
77321 * Creates recipient headers.
77322 * @access private
77323 * @return string
77324 */
77325 function AddrAppend($type, $addr) {
77326 $addr_str = $type . ': ';
77327 $addr_str .= $this->AddrFormat($addr[0]);
77328 if(count($addr) > 1) {
77329 for($i = 1; $i < count($addr); $i++) {
77330 $addr_str .= ', ' . $this->AddrFormat($addr[$i]);
77331 }
77332 }
77333 $addr_str .= $this->LE;
77334
77335 return $addr_str;
77336 }
77337
77338 /**
77339 * Formats an address correctly.
77340 * @access private
77341 * @return string
77342 */
77343 function AddrFormat($addr) {
77344 if(empty($addr[1])) {
77345 $formatted = $this->SecureHeader($addr[0]);
77346 } else {
77347 $formatted = $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
77348 }
77349
77350 return $formatted;
77351 }
77352
77353 /**
77354 * Wraps message for use with mailers that do not
77355 * automatically perform wrapping and for quoted-printable.
77356 * Original written by philippe.
77357 * @access private
77358 * @return string
77359 */
77360 function WrapText($message, $length, $qp_mode = false) {
77361 $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
77362 // If utf-8 encoding is used, we will need to make sure we don't
77363 // split multibyte characters when we wrap
77364 $is_utf8 = (strtolower($this->CharSet) == "utf-8");
77365
77366 $message = $this->FixEOL($message);
77367 if (substr($message, -1) == $this->LE) {
77368 $message = substr($message, 0, -1);
77369 }
77370
77371 $line = explode($this->LE, $message);
77372 $message = '';
77373 for ($i=0 ;$i < count($line); $i++) {
77374 $line_part = explode(' ', $line[$i]);
77375 $buf = '';
77376 for ($e = 0; $e<count($line_part); $e++) {
77377 $word = $line_part[$e];
77378 if ($qp_mode and (strlen($word) > $length)) {
77379 $space_left = $length - strlen($buf) - 1;
77380 if ($e != 0) {
77381 if ($space_left > 20) {
77382 $len = $space_left;
77383 if ($is_utf8) {
77384 $len = $this->UTF8CharBoundary($word, $len);
77385 } elseif (substr($word, $len - 1, 1) == "=") {
77386 $len--;
77387 } elseif (substr($word, $len - 2, 1) == "=") {
77388 $len -= 2;
77389 }
77390 $part = substr($word, 0, $len);
77391 $word = substr($word, $len);
77392 $buf .= ' ' . $part;
77393 $message .= $buf . sprintf("=%s", $this->LE);
77394 } else {
77395 $message .= $buf . $soft_break;
77396 }
77397 $buf = '';
77398 }
77399 while (strlen($word) > 0) {
77400 $len = $length;
77401 if ($is_utf8) {
77402 $len = $this->UTF8CharBoundary($word, $len);
77403 } elseif (substr($word, $len - 1, 1) == "=") {
77404 $len--;
77405 } elseif (substr($word, $len - 2, 1) == "=") {
77406 $len -= 2;
77407 }
77408 $part = substr($word, 0, $len);
77409 $word = substr($word, $len);
77410
77411 if (strlen($word) > 0) {
77412 $message .= $part . sprintf("=%s", $this->LE);
77413 } else {
77414 $buf = $part;
77415 }
77416 }
77417 } else {
77418 $buf_o = $buf;
77419 $buf .= ($e == 0) ? $word : (' ' . $word);
77420
77421 if (strlen($buf) > $length and $buf_o != '') {
77422 $message .= $buf_o . $soft_break;
77423 $buf = $word;
77424 }
77425 }
77426 }
77427 $message .= $buf . $this->LE;
77428 }
77429
77430 return $message;
77431 }
77432
77433 /**
77434 * Finds last character boundary prior to maxLength in a utf-8
77435 * quoted (printable) encoded string.
77436 * Original written by Colin Brown.
77437 * @access private
77438 * @param string $encodedText utf-8 QP text
77439 * @param int $maxLength find last character boundary prior to this length
77440 * @return int
77441 */
77442 function UTF8CharBoundary($encodedText, $maxLength) {
77443 $foundSplitPos = false;
77444 $lookBack = 3;
77445 while (!$foundSplitPos) {
77446 $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
77447 $encodedCharPos = strpos($lastChunk, "=");
77448 if ($encodedCharPos !== false) {
77449 // Found start of encoded character byte within $lookBack block.
77450 // Check the encoded byte value (the 2 chars after the '=')
77451 $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
77452 $dec = hexdec($hex);
77453 if ($dec < 128) { // Single byte character.
77454 // If the encoded char was found at pos 0, it will fit
77455 // otherwise reduce maxLength to start of the encoded char
77456 $maxLength = ($encodedCharPos == 0) ? $maxLength :
77457 $maxLength - ($lookBack - $encodedCharPos);
77458 $foundSplitPos = true;
77459 } elseif ($dec >= 192) { // First byte of a multi byte character
77460 // Reduce maxLength to split at start of character
77461 $maxLength = $maxLength - ($lookBack - $encodedCharPos);
77462 $foundSplitPos = true;
77463 } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back
77464 $lookBack += 3;
77465 }
77466 } else {
77467 // No encoded character found
77468 $foundSplitPos = true;
77469 }
77470 }
77471 return $maxLength;
77472 }
77473
77474 /**
77475 * Set the body wrapping.
77476 * @access private
77477 * @return void
77478 */
77479 function SetWordWrap() {
77480 if($this->WordWrap < 1) {
77481 return;
77482 }
77483
77484 switch($this->message_type) {
77485 case 'alt':
77486 /* fall through */
77487 case 'alt_attachments':
77488 $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
77489 break;
77490 default:
77491 $this->Body = $this->WrapText($this->Body, $this->WordWrap);
77492 break;
77493 }
77494 }
77495
77496 /**
77497 * Assembles message header.
77498 * @access private
77499 * @return string
77500 */
77501 function CreateHeader() {
77502 $result = '';
77503
77504 /* Set the boundaries */
77505 $uniq_id = md5(uniqid(time()));
77506 $this->boundary[1] = 'b1_' . $uniq_id;
77507 $this->boundary[2] = 'b2_' . $uniq_id;
77508
77509 $result .= $this->HeaderLine('Date', $this->RFCDate());
77510 if($this->Sender == '') {
77511 $result .= $this->HeaderLine('Return-Path', trim($this->From));
77512 } else {
77513 $result .= $this->HeaderLine('Return-Path', trim($this->Sender));
77514 }
77515
77516 /* To be created automatically by mail() */
77517 if($this->Mailer != 'mail') {
77518 if(count($this->to) > 0) {
77519 $result .= $this->AddrAppend('To', $this->to);
77520 } elseif (count($this->cc) == 0) {
77521 $result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
77522 }
77523 if(count($this->cc) > 0) {
77524 $result .= $this->AddrAppend('Cc', $this->cc);
77525 }
77526 }
77527
77528 $from = array();
77529 $from[0][0] = trim($this->From);
77530 $from[0][1] = $this->FromName;
77531 $result .= $this->AddrAppend('From', $from);
77532
77533 /* sendmail and mail() extract Cc from the header before sending */
77534 if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->cc) > 0)) {
77535 $result .= $this->AddrAppend('Cc', $this->cc);
77536 }
77537
77538 /* sendmail and mail() extract Bcc from the header before sending */
77539 if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
77540 $result .= $this->AddrAppend('Bcc', $this->bcc);
77541 }
77542
77543 if(count($this->ReplyTo) > 0) {
77544 $result .= $this->AddrAppend('Reply-To', $this->ReplyTo);
77545 }
77546
77547 /* mail() sets the subject itself */
77548 if($this->Mailer != 'mail') {
77549 $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
77550 }
77551
77552 if($this->MessageID != '') {
77553 $result .= $this->HeaderLine('Message-ID',$this->MessageID);
77554 } else {
77555 $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
77556 }
77557 $result .= $this->HeaderLine('X-Priority', $this->Priority);
77558 $result .= $this->HeaderLine('X-Mailer', 'PHPMailer (phpmailer.sourceforge.net) [version ' . $this->Version . ']');
77559
77560 if($this->ConfirmReadingTo != '') {
77561 $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
77562 }
77563
77564 // Add custom headers
77565 for($index = 0; $index < count($this->CustomHeader); $index++) {
77566 $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1])));
77567 }
77568 if (!$this->sign_key_file) {
77569 $result .= $this->HeaderLine('MIME-Version', '1.0');
77570 $result .= $this->GetMailMIME();
77571 }
77572
77573 return $result;
77574 }
77575
77576 /**
77577 * Returns the message MIME.
77578 * @access private
77579 * @return string
77580 */
77581 function GetMailMIME() {
77582 $result = '';
77583 switch($this->message_type) {
77584 case 'plain':
77585 $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
77586 $result .= sprintf("Content-Type: %s; charset=\"%s\"", $this->ContentType, $this->CharSet);
77587 break;
77588 case 'attachments':
77589 /* fall through */
77590 case 'alt_attachments':
77591 if($this->InlineImageExists()){
77592 $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE);
77593 } else {
77594 $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');
77595 $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
77596 }
77597 break;
77598 case 'alt':
77599 $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
77600 $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
77601 break;
77602 }
77603
77604 if($this->Mailer != 'mail') {
77605 $result .= $this->LE.$this->LE;
77606 }
77607
77608 return $result;
77609 }
77610
77611 /**
77612 * Assembles the message body. Returns an empty string on failure.
77613 * @access private
77614 * @return string
77615 */
77616 function CreateBody() {
77617 $result = '';
77618 if ($this->sign_key_file) {
77619 $result .= $this->GetMailMIME();
77620 }
77621
77622 $this->SetWordWrap();
77623
77624 switch($this->message_type) {
77625 case 'alt':
77626 $result .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
77627 $result .= $this->EncodeString($this->AltBody, $this->Encoding);
77628 $result .= $this->LE.$this->LE;
77629 $result .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
77630 $result .= $this->EncodeString($this->Body, $this->Encoding);
77631 $result .= $this->LE.$this->LE;
77632 $result .= $this->EndBoundary($this->boundary[1]);
77633 break;
77634 case 'plain':
77635 $result .= $this->EncodeString($this->Body, $this->Encoding);
77636 break;
77637 case 'attachments':
77638 $result .= $this->GetBoundary($this->boundary[1], '', '', '');
77639 $result .= $this->EncodeString($this->Body, $this->Encoding);
77640 $result .= $this->LE;
77641 $result .= $this->AttachAll();
77642 break;
77643 case 'alt_attachments':
77644 $result .= sprintf("--%s%s", $this->boundary[1], $this->LE);
77645 $result .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE);
77646 $result .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body
77647 $result .= $this->EncodeString($this->AltBody, $this->Encoding);
77648 $result .= $this->LE.$this->LE;
77649 $result .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body
77650 $result .= $this->EncodeString($this->Body, $this->Encoding);
77651 $result .= $this->LE.$this->LE;
77652 $result .= $this->EndBoundary($this->boundary[2]);
77653 $result .= $this->AttachAll();
77654 break;
77655 }
77656
77657 if($this->IsError()) {
77658 $result = '';
77659 } else if ($this->sign_key_file) {
77660 $file = tempnam("", "mail");
77661 $fp = fopen($file, "w");
77662 fwrite($fp, $result);
77663 fclose($fp);
77664 $signed = tempnam("", "signed");
77665
77666 if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_key_file, array("file://".$this->sign_key_file, $this->sign_key_pass), null)) {
77667 $fp = fopen($signed, "r");
77668 $result = fread($fp, filesize($this->sign_key_file));
77669 fclose($fp);
77670 } else {
77671 $this->SetError($this->Lang("signing").openssl_error_string());
77672 $result = '';
77673 }
77674
77675 unlink($file);
77676 unlink($signed);
77677 }
77678
77679 return $result;
77680 }
77681
77682 /**
77683 * Returns the start of a message boundary.
77684 * @access private
77685 */
77686 function GetBoundary($boundary, $charSet, $contentType, $encoding) {
77687 $result = '';
77688 if($charSet == '') {
77689 $charSet = $this->CharSet;
77690 }
77691 if($contentType == '') {
77692 $contentType = $this->ContentType;
77693 }
77694 if($encoding == '') {
77695 $encoding = $this->Encoding;
77696 }
77697 $result .= $this->TextLine('--' . $boundary);
77698 $result .= sprintf("Content-Type: %s; charset = \"%s\"", $contentType, $charSet);
77699 $result .= $this->LE;
77700 $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding);
77701 $result .= $this->LE;
77702
77703 return $result;
77704 }
77705
77706 /**
77707 * Returns the end of a message boundary.
77708 * @access private
77709 */
77710 function EndBoundary($boundary) {
77711 return $this->LE . '--' . $boundary . '--' . $this->LE;
77712 }
77713
77714 /**
77715 * Sets the message type.
77716 * @access private
77717 * @return void
77718 */
77719 function SetMessageType() {
77720 if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) {
77721 $this->message_type = 'plain';
77722 } else {
77723 if(count($this->attachment) > 0) {
77724 $this->message_type = 'attachments';
77725 }
77726 if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) {
77727 $this->message_type = 'alt';
77728 }
77729 if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) {
77730 $this->message_type = 'alt_attachments';
77731 }
77732 }
77733 }
77734
77735 /* Returns a formatted header line.
77736 * @access private
77737 * @return string
77738 */
77739 function HeaderLine($name, $value) {
77740 return $name . ': ' . $value . $this->LE;
77741 }
77742
77743 /**
77744 * Returns a formatted mail line.
77745 * @access private
77746 * @return string
77747 */
77748 function TextLine($value) {
77749 return $value . $this->LE;
77750 }
77751
77752 /////////////////////////////////////////////////
77753 // CLASS METHODS, ATTACHMENTS
77754 /////////////////////////////////////////////////
77755
77756 /**
77757 * Adds an attachment from a path on the filesystem.
77758 * Returns false if the file could not be found
77759 * or accessed.
77760 * @param string $path Path to the attachment.
77761 * @param string $name Overrides the attachment name.
77762 * @param string $encoding File encoding (see $Encoding).
77763 * @param string $type File extension (MIME) type.
77764 * @return bool
77765 */
77766 function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
77767 if(!@is_file($path)) {
77768 $this->SetError($this->Lang('file_access') . $path);
77769 return false;
77770 }
77771
77772 $filename = basename($path);
77773 if($name == '') {
77774 $name = $filename;
77775 }
77776
77777 $cur = count($this->attachment);
77778 $this->attachment[$cur][0] = $path;
77779 $this->attachment[$cur][1] = $filename;
77780 $this->attachment[$cur][2] = $name;
77781 $this->attachment[$cur][3] = $encoding;
77782 $this->attachment[$cur][4] = $type;
77783 $this->attachment[$cur][5] = false; // isStringAttachment
77784 $this->attachment[$cur][6] = 'attachment';
77785 $this->attachment[$cur][7] = 0;
77786
77787 return true;
77788 }
77789
77790 /**
77791 * Attaches all fs, string, and binary attachments to the message.
77792 * Returns an empty string on failure.
77793 * @access private
77794 * @return string
77795 */
77796 function AttachAll() {
77797 /* Return text of body */
77798 $mime = array();
77799
77800 /* Add all attachments */
77801 for($i = 0; $i < count($this->attachment); $i++) {
77802 /* Check for string attachment */
77803 $bString = $this->attachment[$i][5];
77804 if ($bString) {
77805 $string = $this->attachment[$i][0];
77806 } else {
77807 $path = $this->attachment[$i][0];
77808 }
77809
77810 $filename = $this->attachment[$i][1];
77811 $name = $this->attachment[$i][2];
77812 $encoding = $this->attachment[$i][3];
77813 $type = $this->attachment[$i][4];
77814 $disposition = $this->attachment[$i][6];
77815 $cid = $this->attachment[$i][7];
77816
77817 $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);
77818 $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $name, $this->LE);
77819 $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
77820
77821 if($disposition == 'inline') {
77822 $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
77823 }
77824
77825 $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $name, $this->LE.$this->LE);
77826
77827 /* Encode as string attachment */
77828 if($bString) {
77829 $mime[] = $this->EncodeString($string, $encoding);
77830 if($this->IsError()) {
77831 return '';
77832 }
77833 $mime[] = $this->LE.$this->LE;
77834 } else {
77835 $mime[] = $this->EncodeFile($path, $encoding);
77836 if($this->IsError()) {
77837 return '';
77838 }
77839 $mime[] = $this->LE.$this->LE;
77840 }
77841 }
77842
77843 $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE);
77844
77845 return join('', $mime);
77846 }
77847
77848 /**
77849 * Encodes attachment in requested format. Returns an
77850 * empty string on failure.
77851 * @access private
77852 * @return string
77853 */
77854 function EncodeFile ($path, $encoding = 'base64') {
77855 if(!@$fd = fopen($path, 'rb')) {
77856 $this->SetError($this->Lang('file_open') . $path);
77857 return '';
77858 }
77859 $magic_quotes = get_magic_quotes_runtime();
77860 set_magic_quotes_runtime(0);
77861 $file_buffer = fread($fd, filesize($path));
77862 $file_buffer = $this->EncodeString($file_buffer, $encoding);
77863 fclose($fd);
77864 set_magic_quotes_runtime($magic_quotes);
77865
77866 return $file_buffer;
77867 }
77868
77869 /**
77870 * Encodes string to requested format. Returns an
77871 * empty string on failure.
77872 * @access private
77873 * @return string
77874 */
77875 function EncodeString ($str, $encoding = 'base64') {
77876 $encoded = '';
77877 switch(strtolower($encoding)) {
77878 case 'base64':
77879 /* chunk_split is found in PHP >= 3.0.6 */
77880 $encoded = chunk_split(base64_encode($str), 76, $this->LE);
77881 break;
77882 case '7bit':
77883 case '8bit':
77884 $encoded = $this->FixEOL($str);
77885 if (substr($encoded, -(strlen($this->LE))) != $this->LE)
77886 $encoded .= $this->LE;
77887 break;
77888 case 'binary':
77889 $encoded = $str;
77890 break;
77891 case 'quoted-printable':
77892 $encoded = $this->EncodeQP($str);
77893 break;
77894 default:
77895 $this->SetError($this->Lang('encoding') . $encoding);
77896 break;
77897 }
77898 return $encoded;
77899 }
77900
77901 /**
77902 * Encode a header string to best of Q, B, quoted or none.
77903 * @access private
77904 * @return string
77905 */
77906 function EncodeHeader ($str, $position = 'text') {
77907 $x = 0;
77908
77909 switch (strtolower($position)) {
77910 case 'phrase':
77911 if (!preg_match('/[\200-\377]/', $str)) {
77912 /* Can't use addslashes as we don't know what value has magic_quotes_sybase. */
77913 $encoded = addcslashes($str, "\0..\37\177\\\"");
77914 if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
77915 return ($encoded);
77916 } else {
77917 return ("\"$encoded\"");
77918 }
77919 }
77920 $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
77921 break;
77922 case 'comment':
77923 $x = preg_match_all('/[()"]/', $str, $matches);
77924 /* Fall-through */
77925 case 'text':
77926 default:
77927 $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
77928 break;
77929 }
77930
77931 if ($x == 0) {
77932 return ($str);
77933 }
77934
77935 $maxlen = 75 - 7 - strlen($this->CharSet);
77936 /* Try to select the encoding which should produce the shortest output */
77937 if (strlen($str)/3 < $x) {
77938 $encoding = 'B';
77939 if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) {
77940 // Use a custom function which correctly encodes and wraps long
77941 // multibyte strings without breaking lines within a character
77942 $encoded = $this->Base64EncodeWrapMB($str);
77943 } else {
77944 $encoded = base64_encode($str);
77945 $maxlen -= $maxlen % 4;
77946 $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
77947 }
77948 } else {
77949 $encoding = 'Q';
77950 $encoded = $this->EncodeQ($str, $position);
77951 $encoded = $this->WrapText($encoded, $maxlen, true);
77952 $encoded = str_replace('='.$this->LE, "\n", trim($encoded));
77953 }
77954
77955 $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);
77956 $encoded = trim(str_replace("\n", $this->LE, $encoded));
77957
77958 return $encoded;
77959 }
77960
77961 /**
77962 * Checks if a string contains multibyte characters.
77963 * @access private
77964 * @param string $str multi-byte text to wrap encode
77965 * @return bool
77966 */
77967 function HasMultiBytes($str) {
77968 if (function_exists('mb_strlen')) {
77969 return (strlen($str) > mb_strlen($str, $this->CharSet));
77970 } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
77971 return False;
77972 }
77973 }
77974
77975 /**
77976 * Correctly encodes and wraps long multibyte strings for mail headers
77977 * without breaking lines within a character.
77978 * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php
77979 * @access private
77980 * @param string $str multi-byte text to wrap encode
77981 * @return string
77982 */
77983 function Base64EncodeWrapMB($str) {
77984 $start = "=?".$this->CharSet."?B?";
77985 $end = "?=";
77986 $encoded = "";
77987
77988 $mb_length = mb_strlen($str, $this->CharSet);
77989 // Each line must have length <= 75, including $start and $end
77990 $length = 75 - strlen($start) - strlen($end);
77991 // Average multi-byte ratio
77992 $ratio = $mb_length / strlen($str);
77993 // Base64 has a 4:3 ratio
77994 $offset = $avgLength = floor($length * $ratio * .75);
77995
77996 for ($i = 0; $i < $mb_length; $i += $offset) {
77997 $lookBack = 0;
77998
77999 do {
78000 $offset = $avgLength - $lookBack;
78001 $chunk = mb_substr($str, $i, $offset, $this->CharSet);
78002 $chunk = base64_encode($chunk);
78003 $lookBack++;
78004 }
78005 while (strlen($chunk) > $length);
78006
78007 $encoded .= $chunk . $this->LE;
78008 }
78009
78010 // Chomp the last linefeed
78011 $encoded = substr($encoded, 0, -strlen($this->LE));
78012 return $encoded;
78013 }
78014
78015 /**
78016 * Encode string to quoted-printable.
78017 * @access private
78018 * @return string
78019 */
78020 function EncodeQP( $input = '', $line_max = 76, $space_conv = false ) {
78021 $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
78022 $lines = preg_split('/(?:\r\n|\r|\n)/', $input);
78023 $eol = "\r\n";
78024 $escape = '=';
78025 $output = '';
78026 while( list(, $line) = each($lines) ) {
78027 $linlen = strlen($line);
78028 $newline = '';
78029 for($i = 0; $i < $linlen; $i++) {
78030 $c = substr( $line, $i, 1 );
78031 $dec = ord( $c );
78032 if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E
78033 $c = '=2E';
78034 }
78035 if ( $dec == 32 ) {
78036 if ( $i == ( $linlen - 1 ) ) { // convert space at eol only
78037 $c = '=20';
78038 } else if ( $space_conv ) {
78039 $c = '=20';
78040 }
78041 } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
78042 $h2 = floor($dec/16);
78043 $h1 = floor($dec%16);
78044 $c = $escape.$hex[$h2].$hex[$h1];
78045 }
78046 if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
78047 $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
78048 $newline = '';
78049 // check if newline first character will be point or not
78050 if ( $dec == 46 ) {
78051 $c = '=2E';
78052 }
78053 }
78054 $newline .= $c;
78055 } // end of for
78056 $output .= $newline.$eol;
78057 } // end of while
78058 return trim($output);
78059 }
78060
78061 /**
78062 * Encode string to q encoding.
78063 * @access private
78064 * @return string
78065 */
78066 function EncodeQ ($str, $position = 'text') {
78067 /* There should not be any EOL in the string */
78068 $encoded = preg_replace("[\r\n]", '', $str);
78069
78070 switch (strtolower($position)) {
78071 case 'phrase':
78072 $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
78073 break;
78074 case 'comment':
78075 $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
78076 case 'text':
78077 default:
78078 /* Replace every high ascii, control =, ? and _ characters */
78079 $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
78080 "'='.sprintf('%02X', ord('\\1'))", $encoded);
78081 break;
78082 }
78083
78084 /* Replace every spaces to _ (more readable than =20) */
78085 $encoded = str_replace(' ', '_', $encoded);
78086
78087 return $encoded;
78088 }
78089
78090 /**
78091 * Adds a string or binary attachment (non-filesystem) to the list.
78092 * This method can be used to attach ascii or binary data,
78093 * such as a BLOB record from a database.
78094 * @param string $string String attachment data.
78095 * @param string $filename Name of the attachment.
78096 * @param string $encoding File encoding (see $Encoding).
78097 * @param string $type File extension (MIME) type.
78098 * @return void
78099 */
78100 function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') {
78101 /* Append to $attachment array */
78102 $cur = count($this->attachment);
78103 $this->attachment[$cur][0] = $string;
78104 $this->attachment[$cur][1] = $filename;
78105 $this->attachment[$cur][2] = $filename;
78106 $this->attachment[$cur][3] = $encoding;
78107 $this->attachment[$cur][4] = $type;
78108 $this->attachment[$cur][5] = true; // isString
78109 $this->attachment[$cur][6] = 'attachment';
78110 $this->attachment[$cur][7] = 0;
78111 }
78112
78113 /**
78114 * Adds an embedded attachment. This can include images, sounds, and
78115 * just about any other document. Make sure to set the $type to an
78116 * image type. For JPEG images use "image/jpeg" and for GIF images
78117 * use "image/gif".
78118 * @param string $path Path to the attachment.
78119 * @param string $cid Content ID of the attachment. Use this to identify
78120 * the Id for accessing the image in an HTML form.
78121 * @param string $name Overrides the attachment name.
78122 * @param string $encoding File encoding (see $Encoding).
78123 * @param string $type File extension (MIME) type.
78124 * @return bool
78125 */
78126 function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
78127
78128 if(!@is_file($path)) {
78129 $this->SetError($this->Lang('file_access') . $path);
78130 return false;
78131 }
78132
78133 $filename = basename($path);
78134 if($name == '') {
78135 $name = $filename;
78136 }
78137
78138 /* Append to $attachment array */
78139 $cur = count($this->attachment);
78140 $this->attachment[$cur][0] = $path;
78141 $this->attachment[$cur][1] = $filename;
78142 $this->attachment[$cur][2] = $name;
78143 $this->attachment[$cur][3] = $encoding;
78144 $this->attachment[$cur][4] = $type;
78145 $this->attachment[$cur][5] = false;
78146 $this->attachment[$cur][6] = 'inline';
78147 $this->attachment[$cur][7] = $cid;
78148
78149 return true;
78150 }
78151
78152 /**
78153 * Returns true if an inline attachment is present.
78154 * @access private
78155 * @return bool
78156 */
78157 function InlineImageExists() {
78158 $result = false;
78159 for($i = 0; $i < count($this->attachment); $i++) {
78160 if($this->attachment[$i][6] == 'inline') {
78161 $result = true;
78162 break;
78163 }
78164 }
78165
78166 return $result;
78167 }
78168
78169 /////////////////////////////////////////////////
78170 // CLASS METHODS, MESSAGE RESET
78171 /////////////////////////////////////////////////
78172
78173 /**
78174 * Clears all recipients assigned in the TO array. Returns void.
78175 * @return void
78176 */
78177 function ClearAddresses() {
78178 $this->to = array();
78179 }
78180
78181 /**
78182 * Clears all recipients assigned in the CC array. Returns void.
78183 * @return void
78184 */
78185 function ClearCCs() {
78186 $this->cc = array();
78187 }
78188
78189 /**
78190 * Clears all recipients assigned in the BCC array. Returns void.
78191 * @return void
78192 */
78193 function ClearBCCs() {
78194 $this->bcc = array();
78195 }
78196
78197 /**
78198 * Clears all recipients assigned in the ReplyTo array. Returns void.
78199 * @return void
78200 */
78201 function ClearReplyTos() {
78202 $this->ReplyTo = array();
78203 }
78204
78205 /**
78206 * Clears all recipients assigned in the TO, CC and BCC
78207 * array. Returns void.
78208 * @return void
78209 */
78210 function ClearAllRecipients() {
78211 $this->to = array();
78212 $this->cc = array();
78213 $this->bcc = array();
78214 }
78215
78216 /**
78217 * Clears all previously set filesystem, string, and binary
78218 * attachments. Returns void.
78219 * @return void
78220 */
78221 function ClearAttachments() {
78222 $this->attachment = array();
78223 }
78224
78225 /**
78226 * Clears all custom headers. Returns void.
78227 * @return void
78228 */
78229 function ClearCustomHeaders() {
78230 $this->CustomHeader = array();
78231 }
78232
78233 /////////////////////////////////////////////////
78234 // CLASS METHODS, MISCELLANEOUS
78235 /////////////////////////////////////////////////
78236
78237 /**
78238 * Adds the error message to the error container.
78239 * Returns void.
78240 * @access private
78241 * @return void
78242 */
78243 function SetError($msg) {
78244 $this->error_count++;
78245 $this->ErrorInfo = $msg;
78246 }
78247
78248 /**
78249 * Returns the proper RFC 822 formatted date.
78250 * @access private
78251 * @return string
78252 */
78253 function RFCDate() {
78254 $tz = date('Z');
78255 $tzs = ($tz < 0) ? '-' : '+';
78256 $tz = abs($tz);
78257 $tz = (int)($tz/3600)*100 + ($tz%3600)/60;
78258 $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz);
78259
78260 return $result;
78261 }
78262
78263 /**
78264 * Returns the appropriate server variable. Should work with both
78265 * PHP 4.1.0+ as well as older versions. Returns an empty string
78266 * if nothing is found.
78267 * @access private
78268 * @return mixed
78269 */
78270 function ServerVar($varName) {
78271 global $HTTP_SERVER_VARS;
78272 global $HTTP_ENV_VARS;
78273
78274 if(!isset($_SERVER)) {
78275 $_SERVER = $HTTP_SERVER_VARS;
78276 if(!isset($_SERVER['REMOTE_ADDR'])) {
78277 $_SERVER = $HTTP_ENV_VARS; // must be Apache
78278 }
78279 }
78280
78281 if(isset($_SERVER[$varName])) {
78282 return $_SERVER[$varName];
78283 } else {
78284 return '';
78285 }
78286 }
78287
78288 /**
78289 * Returns the server hostname or 'localhost.localdomain' if unknown.
78290 * @access private
78291 * @return string
78292 */
78293 function ServerHostname() {
78294 if ($this->Hostname != '') {
78295 $result = $this->Hostname;
78296 } elseif ($this->ServerVar('SERVER_NAME') != '') {
78297 $result = $this->ServerVar('SERVER_NAME');
78298 } else {
78299 $result = 'localhost.localdomain';
78300 }
78301
78302 return $result;
78303 }
78304
78305 /**
78306 * Returns a message in the appropriate language.
78307 * @access private
78308 * @return string
78309 */
78310 function Lang($key) {
78311 if(count($this->language) < 1) {
78312 $this->SetLanguage('en'); // set the default language
78313 }
78314
78315 if(isset($this->language[$key])) {
78316 return $this->language[$key];
78317 } else {
78318 return 'Language string failed to load: ' . $key;
78319 }
78320 }
78321
78322 /**
78323 * Returns true if an error occurred.
78324 * @return bool
78325 */
78326 function IsError() {
78327 return ($this->error_count > 0);
78328 }
78329
78330 /**
78331 * Changes every end of line from CR or LF to CRLF.
78332 * @access private
78333 * @return string
78334 */
78335 function FixEOL($str) {
78336 $str = str_replace("\r\n", "\n", $str);
78337 $str = str_replace("\r", "\n", $str);
78338 $str = str_replace("\n", $this->LE, $str);
78339 return $str;
78340 }
78341
78342 /**
78343 * Adds a custom header.
78344 * @return void
78345 */
78346 function AddCustomHeader($custom_header) {
78347 $this->CustomHeader[] = explode(':', $custom_header, 2);
78348 }
78349
78350 /**
78351 * Evaluates the message and returns modifications for inline images and backgrounds
78352 * @access public
78353 * @return $message
78354 */
78355 function MsgHTML($message,$basedir='') {
78356 preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images);
78357 if(isset($images[2])) {
78358 foreach($images[2] as $i => $url) {
78359 // do not change urls for absolute images (thanks to corvuscorax)
78360 if (!preg_match('/^[A-z][A-z]*:\/\//',$url)) {
78361 $filename = basename($url);
78362 $directory = dirname($url);
78363 ($directory == '.')?$directory='':'';
78364 $cid = 'cid:' . md5($filename);
78365 $fileParts = split("\.", $filename);
78366 $ext = $fileParts[1];
78367 $mimeType = $this->_mime_types($ext);
78368 if ( strlen($basedir) > 1 && substr($basedir,-1) != '/') { $basedir .= '/'; }
78369 if ( strlen($directory) > 1 && substr($basedir,-1) != '/') { $directory .= '/'; }
78370 $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64', $mimeType);
78371 if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64',$mimeType) ) {
78372 $message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message);
78373 }
78374 }
78375 }
78376 }
78377 $this->IsHTML(true);
78378 $this->Body = $message;
78379 $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s','',$message)));
78380 if ( !empty($textMsg) && empty($this->AltBody) ) {
78381 $this->AltBody = $textMsg;
78382 }
78383 if ( empty($this->AltBody) ) {
78384 $this->AltBody = 'To view this email message, open the email in with HTML compatibility!' . "\n\n";
78385 }
78386 }
78387
78388 /**
78389 * Gets the mime type of the embedded or inline image
78390 * @access private
78391 * @return mime type of ext
78392 */
78393 function _mime_types($ext = '') {
78394 $mimes = array(
78395 'hqx' => 'application/mac-binhex40',
78396 'cpt' => 'application/mac-compactpro',
78397 'doc' => 'application/msword',
78398 'bin' => 'application/macbinary',
78399 'dms' => 'application/octet-stream',
78400 'lha' => 'application/octet-stream',
78401 'lzh' => 'application/octet-stream',
78402 'exe' => 'application/octet-stream',
78403 'class' => 'application/octet-stream',
78404 'psd' => 'application/octet-stream',
78405 'so' => 'application/octet-stream',
78406 'sea' => 'application/octet-stream',
78407 'dll' => 'application/octet-stream',
78408 'oda' => 'application/oda',
78409 'pdf' => 'application/pdf',
78410 'ai' => 'application/postscript',
78411 'eps' => 'application/postscript',
78412 'ps' => 'application/postscript',
78413 'smi' => 'application/smil',
78414 'smil' => 'application/smil',
78415 'mif' => 'application/vnd.mif',
78416 'xls' => 'application/vnd.ms-excel',
78417 'ppt' => 'application/vnd.ms-powerpoint',
78418 'wbxml' => 'application/vnd.wap.wbxml',
78419 'wmlc' => 'application/vnd.wap.wmlc',
78420 'dcr' => 'application/x-director',
78421 'dir' => 'application/x-director',
78422 'dxr' => 'application/x-director',
78423 'dvi' => 'application/x-dvi',
78424 'gtar' => 'application/x-gtar',
78425 'php' => 'application/x-httpd-php',
78426 'php4' => 'application/x-httpd-php',
78427 'php3' => 'application/x-httpd-php',
78428 'phtml' => 'application/x-httpd-php',
78429 'phps' => 'application/x-httpd-php-source',
78430 'js' => 'application/x-javascript',
78431 'swf' => 'application/x-shockwave-flash',
78432 'sit' => 'application/x-stuffit',
78433 'tar' => 'application/x-tar',
78434 'tgz' => 'application/x-tar',
78435 'xhtml' => 'application/xhtml+xml',
78436 'xht' => 'application/xhtml+xml',
78437 'zip' => 'application/zip',
78438 'mid' => 'audio/midi',
78439 'midi' => 'audio/midi',
78440 'mpga' => 'audio/mpeg',
78441 'mp2' => 'audio/mpeg',
78442 'mp3' => 'audio/mpeg',
78443 'aif' => 'audio/x-aiff',
78444 'aiff' => 'audio/x-aiff',
78445 'aifc' => 'audio/x-aiff',
78446 'ram' => 'audio/x-pn-realaudio',
78447 'rm' => 'audio/x-pn-realaudio',
78448 'rpm' => 'audio/x-pn-realaudio-plugin',
78449 'ra' => 'audio/x-realaudio',
78450 'rv' => 'video/vnd.rn-realvideo',
78451 'wav' => 'audio/x-wav',
78452 'bmp' => 'image/bmp',
78453 'gif' => 'image/gif',
78454 'jpeg' => 'image/jpeg',
78455 'jpg' => 'image/jpeg',
78456 'jpe' => 'image/jpeg',
78457 'png' => 'image/png',
78458 'tiff' => 'image/tiff',
78459 'tif' => 'image/tiff',
78460 'css' => 'text/css',
78461 'html' => 'text/html',
78462 'htm' => 'text/html',
78463 'shtml' => 'text/html',
78464 'txt' => 'text/plain',
78465 'text' => 'text/plain',
78466 'log' => 'text/plain',
78467 'rtx' => 'text/richtext',
78468 'rtf' => 'text/rtf',
78469 'xml' => 'text/xml',
78470 'xsl' => 'text/xml',
78471 'mpeg' => 'video/mpeg',
78472 'mpg' => 'video/mpeg',
78473 'mpe' => 'video/mpeg',
78474 'qt' => 'video/quicktime',
78475 'mov' => 'video/quicktime',
78476 'avi' => 'video/x-msvideo',
78477 'movie' => 'video/x-sgi-movie',
78478 'doc' => 'application/msword',
78479 'word' => 'application/msword',
78480 'xl' => 'application/excel',
78481 'eml' => 'message/rfc822'
78482 );
78483 return ( ! isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];
78484 }
78485
78486 /**
78487 * Set (or reset) Class Objects (variables)
78488 *
78489 * Usage Example:
78490 * $page->set('X-Priority', '3');
78491 *
78492 * @access public
78493 * @param string $name Parameter Name
78494 * @param mixed $value Parameter Value
78495 * NOTE: will not work with arrays, there are no arrays to set/reset
78496 */
78497 function set ( $name, $value = '' ) {
78498 if ( isset($this->$name) ) {
78499 $this->$name = $value;
78500 } else {
78501 $this->SetError('Cannot set or reset variable ' . $name);
78502 return false;
78503 }
78504 }
78505
78506 /**
78507 * Read a file from a supplied filename and return it.
78508 *
78509 * @access public
78510 * @param string $filename Parameter File Name
78511 */
78512 function getFile($filename) {
78513 $return = '';
78514 if ($fp = fopen($filename, 'rb')) {
78515 while (!feof($fp)) {
78516 $return .= fread($fp, 1024);
78517 }
78518 fclose($fp);
78519 return $return;
78520 } else {
78521 return false;
78522 }
78523 }
78524
78525 /**
78526 * Strips newlines to prevent header injection.
78527 * @access private
78528 * @param string $str String
78529 * @return string
78530 */
78531 function SecureHeader($str) {
78532 $str = trim($str);
78533 $str = str_replace("\r", "", $str);
78534 $str = str_replace("\n", "", $str);
78535 return $str;
78536 }
78537
78538 /**
78539 * Set the private key file and password to sign the message.
78540 *
78541 * @access public
78542 * @param string $key_filename Parameter File Name
78543 * @param string $key_pass Password for private key
78544 */
78545 function Sign($key_filename, $key_pass) {
78546 $this->sign_key_file = $key_filename;
78547 $this->sign_key_pass = $key_pass;
78548 }
78549
78550 }
78551
78552 ?>