Source for file class.phpmailer.php
Documentation is available at class.phpmailer.php 
 .---------------------------------------------------------------------------.  
 |  Software: PHPMailer - PHP email class                                    |  
 |   Contact: via sourceforge.net support pages (also www.worxware.com)      |  
 |      Info: http://phpmailer.sourceforge.net                               |  
 |   Support: http://sourceforge.net/projects/phpmailer/                     |  
 | ------------------------------------------------------------------------- |  
 |     Admin: Andy Prevost (project admininistrator)                         |  
 |   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |  
 |          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |  
 |   Founder: Brent R. Matzelle (original founder)                           |  
 | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |  
 | Copyright (c) 2001-2003, Brent R. Matzelle                                |  
 | ------------------------------------------------------------------------- |  
 |   License: Distributed under the Lesser General Public License (LGPL)     |  
 |            http://www.gnu.org/copyleft/lesser.html                        |  
 | This program is distributed in the hope that it will be useful - WITHOUT  |  
 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |  
 | FITNESS FOR A PARTICULAR PURPOSE.                                         |  
 | ------------------------------------------------------------------------- |  
 | We offer a number of paid services (www.worxware.com):                    |  
 | - Web Hosting on highly optimized fast and secure servers                 |  
 | - Technology Consulting                                                   |  
 | - Oursourcing (highly qualified programmers and graphic designers)        |  
 '---------------------------------------------------------------------------'  
 * PHPMailer - PHP email transport class  
 * NOTE: Requires PHP version 5 or later  
 * @package linea21.externals  
 * @copyright 2004 - 2009 Andy Prevost  
 * @version $Id: class.phpmailer.php 447 2009-05-25 01:36:38Z codeworxtech $  
 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License  
if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n");  
  /////////////////////////////////////////////////  
  /////////////////////////////////////////////////  
   * Email priority (1 = High, 3 = Normal, 5 = low).  
   * Sets the CharSet of the message.  
   * Sets the Content-type of the message.  
   * Sets the Encoding of the message. Options for this are  
   *  "8bit", "7bit", "binary", "base64", and "quoted-printable".  
   * Holds the most recent mailer error message.  
   * Sets the From email address for the message.  
  public $From              =  'root@localhost';  
   * Sets the From name of the message.  
   * Sets the Sender email (Return-Path) of the message.  If not empty,  
   * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.  
   * Sets the Subject of the message.  
   * Sets the Body of the message.  This can be either an HTML or text body.  
   * If HTML then run IsHTML(true).  
   * Sets the text-only body of the message.  This automatically sets the  
   * email to multipart/alternative.  This body can be read by mail  
   * clients that do not have HTML email capability such as mutt. Clients  
   * that can read HTML will view the normal Body.  
   * Sets word wrapping on the body of the message to a given number of  
   * Method to send mail: ("mail", "sendmail", or "smtp").  
   * Sets the path of the sendmail program.  
   * Path to PHPMailer plugins.  Useful if the SMTP class  
   * is in a different directory than the PHP include path.  
   * Sets the email address that a reading confirmation will be sent.  
   * Sets the hostname to use in Message-Id and Received headers  
   * and as default HELO string. If empty, the value returned  
   * by SERVER_NAME is used or 'localhost.localdomain'.  
   * Sets the message ID to be used in the Message-Id header.  
   * If empty, a unique id will be generated.  
  /////////////////////////////////////////////////  
  /////////////////////////////////////////////////  
   * Sets the SMTP hosts.  All hosts must be separated by a  
   * semicolon.  You can also specify a different port  
   * for each host by using this format: [hostname:port]  
   * (e.g. "smtp1.example.com:25;smtp2.example.com").  
   * Hosts will be tried in order.  
  public $Host          =  'localhost';  
   * Sets the default SMTP server port.  
   * Sets the SMTP HELO of the message (Default is $Hostname).  
   * Sets connection prefix.  
   * Options are "", "ssl" or "tls"  
   * Sets SMTP authentication. Utilizes the Username and Password variables.  
   * Sets the SMTP server timeout in seconds.  
   * This function will not work with the win32 version.  
   * Sets SMTP class debugging on or off.  
   * Prevents the SMTP connection from being closed after each mail  
   * sending.  If this is set to true then to close the connection  
   * requires an explicit call to SmtpClose().  
   * Provides the ability to have the TO field process individual  
   * emails, instead of sending to entire TO addresses  
   * If SingleTo is true, this provides the array to hold the email addresses  
   * Provides the ability to change the line ending  
   * Used with DKIM DNS Resource Record  
   * Used with DKIM DNS Resource Record  
   * optional, in format of email address 'you@yourdomain.com'  
   * Used with DKIM DNS Resource Record  
   * optional, in format of email address 'you@yourdomain.com'  
   * Used with DKIM DNS Resource Record  
   * optional, in format of email address 'you@yourdomain.com'  
   * Callback Action function name  
   * the function that handles the result of the send email action. Parameters:  
   *   bool    $result        result of the send action  
   *   string  $to            email address of the recipient  
   *   string  $cc            cc email addresses  
   *   string  $bcc           bcc email addresses  
   *   string  $subject       the subject  
   *   string  $body          the email body  
   * Sets the PHPMailer Version number  
  /////////////////////////////////////////////////  
  // PROPERTIES, PRIVATE AND PROTECTED  
  /////////////////////////////////////////////////  
  private   $ReplyTo        =  array();  
  private   $all_recipients =  array();  
  private   $attachment     =  array();  
  private   $CustomHeader   =  array();  
  private   $message_type   =  '';  
  private   $boundary       =  array();  
  private   $error_count    =  0;  
  private   $sign_cert_file =  "";  
  private   $sign_key_file  =  "";  
  private   $sign_key_pass  =  "";  
  private   $exceptions     =  false;  
  /////////////////////////////////////////////////  
  /////////////////////////////////////////////////  
  const STOP_MESSAGE  =  0; // message only, continue processing  
  const STOP_CONTINUE =  1; // message?, likely ok to continue processing  
  const STOP_CRITICAL =  2; // message, plus full stop, critical error reached  
  /////////////////////////////////////////////////  
  /////////////////////////////////////////////////  
   * @param boolean $exceptions Should we throw external exceptions?  
    $this->exceptions =  ($exceptions ==  true);  
   * Sets message type to HTML.  
  public function IsHTML($ishtml =  true) {  
   * Sets Mailer to send message using SMTP.  
   * Sets Mailer to send message using PHP mail() function.  
   * Sets Mailer to send message using the $Sendmail program.  
      $this->Sendmail =  '/var/qmail/bin/sendmail';  
   * Sets Mailer to send message using the qmail MTA.  
      $this->Sendmail =  '/var/qmail/bin/sendmail';  
  /////////////////////////////////////////////////  
  /////////////////////////////////////////////////  
   * @return boolean true on success, false if address already used  
  public function AddAddress($address, $name =  '') {  
    return $this->AddAnAddress('to', $address, $name);  
   * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.  
   * @return boolean true on success, false if address already used  
  public function AddCC($address, $name =  '') {  
    return $this->AddAnAddress('cc', $address, $name);  
   * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.  
   * @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.  
  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  
   * @return boolean true on success, false if address already used or invalid in some way  
  private function AddAnAddress($kind, $address, $name =  '') {  
    if (!preg_match('/^(to|cc|bcc|ReplyTo)$/', $kind)) {  
      echo  'Invalid recipient array: ' .  kind; 
    $address =  trim($address);  
    if (!self::ValidateAddress($address)) {  
      $this->SetError($this->Lang('invalid_address'). ': '.  $address);  
      echo  $this->Lang('invalid_address'). ': '. $address; 
    if ($kind !=  'ReplyTo') {  
      if (!isset ($this->all_recipients[strtolower($address)])) {  
        $this->all_recipients[strtolower($address)] =  true;  
        $this->ReplyTo[strtolower($address)] =  array($address, $name);  
   * Set the From and FromName properties  
  public function SetFrom($address, $name =  '',$auto= 1) {  
    $address =  trim($address);  
    if (!self::ValidateAddress($address)) {  
      $this->SetError($this->Lang('invalid_address'). ': '.  $address);  
      echo  $this->Lang('invalid_address'). ': '. $address; 
      if (empty($this->ReplyTo)) {  
        $this->AddAnAddress('ReplyTo', $address, $name);  
   * 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  
      if(filter_var($address, FILTER_VALIDATE_EMAIL) ===  FALSE) {  
      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);  
  /////////////////////////////////////////////////  
  /////////////////////////////////////////////////  
   * 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.  
      // Set whether the message is multipart/alternative  
      $this->error_count =  0; // reset errors  
      if (empty($this->Body)) {  
      // digitally sign with DKIM if enabled  
        $header =  str_replace("\r\n","\n",$header_dkim) .  $header;  
      // Choose the mailer and send through it  
      echo  $e->getMessage(). "\n"; 
   * Sends mail using the $Sendmail program.  
   * @param string $header The message headers  
   * @param string $body The message body  
        if(!@$mail =  popen($sendmail, 'w')) {  
        fputs($mail, "To: " .  $val .  "\n");  
        // implement call back function if it exists  
        $isSent =  ($result ==  0) ?  1 :  0;  
      if(!@$mail =  popen($sendmail, 'w')) {  
      // implement call back function if it exists  
      $isSent =  ($result ==  0) ?  1 :  0;  
   * Sends mail using the PHP mail() function.  
   * @param string $header The message headers  
   * @param string $body The message body  
  protected function MailSend($header, $body) {  
    foreach($this->to as $t) {  
      $old_from =  ini_get('sendmail_from');  
        foreach ($toArr as $key =>  $val) {  
          // implement call back function if it exists  
          $isSent =  ($rt ==  1) ?  1 :  0;  
        // implement call back function if it exists  
        $isSent =  ($rt ==  1) ?  1 :  0;  
        foreach ($toArr as $key =>  $val) {  
          // implement call back function if it exists  
          $isSent =  ($rt ==  1) ?  1 :  0;  
        // implement call back function if it exists  
        $isSent =  ($rt ==  1) ?  1 :  0;  
      ini_set('sendmail_from', $old_from);  
   * 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  
  protected function SmtpSend($header, $body) {  
    require_once $this->PluginDir .  'class.smtp.php';  
    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])) {  
        // implement call back function if it exists  
        // implement call back function if it exists  
    foreach($this->cc as $cc) {  
      if (!$this->smtp->Recipient($cc[0])) {  
        // implement call back function if it exists  
        // implement call back function if it exists  
    foreach($this->bcc as $bcc) {  
      if (!$this->smtp->Recipient($bcc[0])) {  
        // implement call back function if it exists  
        // implement call back function if it exists  
    if (count($bad_rcpt) >  0 ) { //Create error message for any bad addresses  
      $badaddresses =  implode(', ', $bad_rcpt);  
    if(!$this->smtp->Data($header .  $body)) {  
   * Initiates a connection to an SMTP server.  
   * Returns false if the operation failed.  
      $this->smtp =  new SMTP();  
    $connection =  $this->smtp->Connected();  
    // Retry while there is no connection  
      while($index <  count($hosts) &&  !$connection) {  
        if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) {  
        if ($this->smtp->Connect(($ssl ?  'ssl://': ''). $host, $port, $this->Timeout)) {  
          $hello =  ($this->Helo !=  '' ?  $this->Helo :  $this->ServerHostname());  
          $this->smtp->Hello($hello);  
            if (!$this->smtp->StartTLS()) {  
            //We must resend HELO after tls negotiation  
            $this->smtp->Hello($hello);  
   * Closes the active SMTP session if one exists.  
      if($this->smtp->Connected()) {  
   * 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  
  function SetLanguage($langcode =  'en', $lang_path =  'language/') {  
    //Define full set of translatable strings  
      '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"!  
      if ($langcode !=  'en') { //There is no English translation file  
        $l =  @include $lang_path. 'phpmailer.lang-'. $langcode. '.php';  
      return ($l ==  true); //Returns false if language not found  
   * Return the current array of language strings  
  /////////////////////////////////////////////////  
  // METHODS, MESSAGE CREATION  
  /////////////////////////////////////////////////  
   * Creates recipient headers.  
    $addr_str =  $type .  ': ';  
    $addr_str .=  implode(', ', $addresses);  
   * Formats an address correctly.  
   * 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  
  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  
    $message =  $this->FixEOL($message);  
    if (substr($message, - 1) ==  $this->LE) {  
      $message =  substr($message, 0, - 1);  
    for ($i= 0 ;$i <  count($line); $i++ ) {  
      $line_part =  explode(' ', $line[$i]);  
      for ($e =  0; $e< count($line_part); $e++ ) {  
        if ($qp_mode and (strlen($word) >  $length)) {  
          $space_left =  $length -  strlen($buf) -  1;  
              } elseif (substr($word, $len -  1, 1) ==  "=") {  
              } elseif (substr($word, $len -  2, 1) ==  "=") {  
              $part =  substr($word, 0, $len);  
              $message .=  $buf .  sprintf("=%s", $this->LE);  
              $message .=  $buf .  $soft_break;  
            } elseif (substr($word, $len -  1, 1) ==  "=") {  
            } elseif (substr($word, $len -  2, 1) ==  "=") {  
            $part =  substr($word, 0, $len);  
              $message .=  $part .  sprintf("=%s", $this->LE);  
          $buf .=  ($e ==  0) ?  $word :  (' ' .  $word);  
          if (strlen($buf) >  $length and $buf_o !=  '') {  
            $message .=  $buf_o .  $soft_break;  
      $message .=  $buf .  $this->LE;  
   * Finds last character boundary prior to maxLength in a utf-8  
   * quoted (printable) encoded string.  
   * Original written by Colin Brown.  
   * @param string $encodedText utf-8 QP text  
   * @param int    $maxLength   find last character boundary prior to this length  
    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);  
        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);  
        } elseif ($dec >=  192) { // First byte of a multi byte character  
          // Reduce maxLength to split at start of character  
          $maxLength =  $maxLength -  ($lookBack -  $encodedCharPos);  
        } elseif ($dec <  192) { // Middle byte of a multi byte character, look further back  
        // No encoded character found  
    switch($this->message_type) {  
   * Assembles message header.  
   * @return string The assembled header  
    $this->boundary[1] =  'b1_' .  $uniq_id;  
    $this->boundary[2] =  'b2_' .  $uniq_id;  
    $result .=  $this->HeaderLine('Date', self::RFCDate());  
    // To be created automatically by mail()  
        foreach($this->to as $t) {  
        if(count($this->to) >  0) {  
        } elseif (count($this->cc) ==  0) {  
          $result .=  $this->HeaderLine('To', 'undisclosed-recipients:;');  
    // sendmail and mail() extract Cc from the header before sending  
    if(count($this->cc) >  0) {  
    // sendmail and mail() extract Bcc from the header before sending  
    if((($this->Mailer ==  'sendmail') ||  ($this->Mailer ==  'mail')) &&  (count($this->bcc) >  0)) {  
    if(count($this->ReplyTo) >  0) {  
      $result .=  $this->AddrAppend('Reply-to', $this->ReplyTo);  
    // mail() sets the subject itself  
      $result .=  sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);  
    $result .=  $this->HeaderLine('X-Mailer', 'PHPMailer '. $this->Version. ' (phpmailer.sourceforge.net)');  
    for($index =  0; $index <  count($this->CustomHeader); $index++ ) {  
    if (!$this->sign_key_file) {  
      $result .=  $this->HeaderLine('MIME-Version', '1.0');  
   * Returns the message MIME.  
    switch($this->message_type) {  
          $result .=  sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE);  
          $result .=  $this->HeaderLine('Content-Type', 'multipart/mixed;');  
          $result .=  $this->TextLine("\tboundary=\"" .  $this->boundary[1] .  '"');  
        $result .=  $this->HeaderLine('Content-Type', 'multipart/alternative;');  
        $result .=  $this->TextLine("\tboundary=\"" .  $this->boundary[1] .  '"');  
      $result .=  $this->LE. $this->LE;  
   * Assembles the message body.  Returns an empty string on failure.  
   * @return string The assembled message body  
    if ($this->sign_key_file) {  
    switch($this->message_type) {  
        $body .=  $this->GetBoundary($this->boundary[1], '', 'text/plain', '');  
        $body .=  $this->LE. $this->LE;  
        $body .=  $this->GetBoundary($this->boundary[1], '', 'text/html', '');  
        $body .=  $this->LE. $this->LE;  
        $body .=  $this->EndBoundary($this->boundary[1]);  
        $body .=  $this->GetBoundary($this->boundary[1], '', '', '');  
        $body .=  $this->AttachAll();  
        $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->LE. $this->LE;  
        $body .=  $this->GetBoundary($this->boundary[2], '', 'text/html', '') .  $this->LE; // Create the HTML body  
        $body .=  $this->LE. $this->LE;  
        $body .=  $this->EndBoundary($this->boundary[2]);  
        $body .=  $this->AttachAll();  
    } elseif ($this->sign_key_file) {  
        if (@openssl_pkcs7_sign($file, $signed, "file://". $this->sign_cert_file, array("file://". $this->sign_key_file, $this->sign_key_pass), NULL)) {  
   * Returns the start of a message boundary.  
  private function GetBoundary($boundary, $charSet, $contentType, $encoding) {  
    $result .=  $this->TextLine('--' .  $boundary);  
    $result .=  sprintf("Content-Type: %s; charset = \"%s\"", $contentType, $charSet);  
    $result .=  $this->HeaderLine('Content-Transfer-Encoding', $encoding);  
   * Returns the end of a message boundary.  
  private function EndBoundary($boundary) {  
    return $this->LE .  '--' .  $boundary .  '--' .  $this->LE;  
  private function SetMessageType() {  
      $this->message_type =  'plain';  
      if(count($this->attachment) >  0) {  
        $this->message_type =  'attachments';  
        $this->message_type =  'alt';  
        $this->message_type =  'alt_attachments';  
   *  Returns a formatted header line.  
    return $name .  ': ' .  $value .  $this->LE;  
   * Returns a formatted mail line.  
    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  
   * @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.  
  public function AddAttachment($path, $name =  '', $encoding =  'base64', $type =  'application/octet-stream') {  
      $this->attachment[] =  array(  
      5 =>  false,  // isStringAttachment  
      echo  $e->getMessage(). "\n"; 
      if ( $e->getCode() ==  self::STOP_CRITICAL ) {  
   * Return the current array of attachments  
    return $this->attachment;  
   * Attaches all fs, string, and binary attachments to the message.  
   * Returns an empty string on failure.  
  private function AttachAll() {  
    foreach ($this->attachment as $attachment) {  
      // Check for string attachment  
      $bString =  $attachment[5];  
        $string =  $attachment[0];  
      if (in_array($attachment[0], $incl)) { continue; }  
      $filename    =  $attachment[1];  
      $encoding    =  $attachment[3];  
      $disposition =  $attachment[6];  
      $incl[]      =  $attachment[0];  
      if ( $disposition ==  'inline' && isset ($cidUniq[$cid]) ) { continue; }  
      $mime[] =  sprintf("--%s%s", $this->boundary[1], $this->LE);  
      $mime[] =  sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);  
      if($disposition ==  'inline') {  
        $mime[] =  sprintf("Content-ID: <%s>%s", $cid, $this->LE);  
      // Encode as string attachment  
        $mime[] =  $this->LE. $this->LE;  
        $mime[] =  $this->EncodeFile($path, $encoding);  
        $mime[] =  $this->LE. $this->LE;  
    $mime[] =  sprintf("--%s--%s", $this->boundary[1], $this->LE);  
   * 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'  
  private function EncodeFile($path, $encoding =  'base64') {  
        function get_magic_quotes() {  
      $file_buffer  =  $this->EncodeString($file_buffer, $encoding);  
   * 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'  
        $encoded =  $this->FixEOL($str);  
        //Make sure it ends with a line break  
        $this->SetError($this->Lang('encoding') .  $encoding);  
   * Encode a header string to best (shortest) of Q, B, quoted or none.  
          // Can't use addslashes as we don't know what value has magic_quotes_sybase  
          if (($str ==  $encoded) &&  !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {  
        $x =  preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);  
        $x +=  preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);  
    // Try to select the encoding which should produce the shortest output  
        // Use a custom function which correctly encodes and wraps long  
        // multibyte strings without breaking lines within a character  
      $encoded =  $this->EncodeQ($str, $position);  
      $encoded =  $this->WrapText($encoded, $maxlen, true);  
   * Checks if a string contains multibyte characters.  
   * @param string $str multi-byte text to wrap encode  
    } else { // Assume no multibytes (we can't handle without mbstring functions anyway)  
   * 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  
   * @param string $str multi-byte text to wrap encode  
    $start =  "=?". $this->CharSet. "?B?";  
    // Each line must have length <= 75, including $start and $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) {  
        $offset =  $avgLength -  $lookBack;  
      while (strlen($chunk) >  $length);  
      $encoded .=  $chunk .  $this->LE;  
    // Chomp the last linefeed  
   * Encode string to quoted-printable.  
   * Only uses standard PHP, slow, but will always work  
   * @param string $string the text to encode  
   * @param integer $line_max Number of chars allowed on a line before wrapping  
  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');  
    while( list (, $line) =  each($lines) ) {  
      for($i =  0; $i <  $linlen; $i++ ) {  
        if ( ( $i ==  0 ) &&  ( $dec ==  46 ) ) { // convert first point in the line into =2E  
          if ( $i ==  ( $linlen -  1 ) ) { // convert space at eol only  
          } else if ( $space_conv ) {  
        } elseif ( ($dec ==  61) ||  ($dec <  32 ) ||  ($dec >  126) ) { // always encode "\t", which is *not* required  
          $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  
          // check if newline first character will be point or not  
      $output .=  $newline. $eol;  
   * 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  
   * @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  
  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)  
    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);  
    $out =  preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange  
   * 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  
  public function EncodeQ ($str, $position =  'text') {  
    // There should not be any EOL in the string  
        $encoded =  preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);  
        $encoded =  preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);  
        // 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);  
    // Replace every spaces to _ (more readable than =20)  
   * 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.  
  public function AddStringAttachment($string, $filename, $encoding =  'base64', $type =  'application/octet-stream') {  
    // Append to $attachment array  
    $this->attachment[] =  array(  
    5 =>  true,  // isStringAttachment  
   * 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  
   * @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.  
  public function AddEmbeddedImage($path, $cid, $name =  '', $encoding =  'base64', $type =  'application/octet-stream') {  
      $this->SetError($this->Lang('file_access') .  $path);  
    // Append to $attachment array  
    $this->attachment[] =  array(  
    5 =>  false,  // isStringAttachment  
   * Returns true if an inline attachment is present.  
    foreach($this->attachment as $attachment) {  
      if ($attachment[6] ==  'inline') {  
  /////////////////////////////////////////////////  
  // CLASS METHODS, MESSAGE RESET  
  /////////////////////////////////////////////////  
   * Clears all recipients assigned in the TO array.  Returns void.  
    foreach($this->to as $to) {  
   * Clears all recipients assigned in the CC array.  Returns void.  
    foreach($this->cc as $cc) {  
   * Clears all recipients assigned in the BCC array.  Returns void.  
    foreach($this->bcc as $bcc) {  
      unset ($this->all_recipients[strtolower($bcc[0])]); 
   * Clears all recipients assigned in the ReplyTo array.  Returns void.  
    $this->ReplyTo =  array();  
   * Clears all recipients assigned in the TO, CC and BCC  
    $this->all_recipients =  array();  
   * Clears all previously set filesystem, string, and binary  
   * attachments.  Returns void.  
    $this->attachment =  array();  
   * Clears all custom headers.  Returns void.  
    $this->CustomHeader =  array();  
  /////////////////////////////////////////////////  
  // CLASS METHODS, MISCELLANEOUS  
  /////////////////////////////////////////////////  
   * Adds the error message to the error container.  
      $lasterror =  $this->smtp->getError();  
        $msg .=  '<p>' .  $this->Lang('smtp_error') .  $lasterror['smtp_msg'] .  "</p>\n";  
   * Returns the proper RFC 822 formatted date.  
    $tzs =  ($tz <  0) ?  '-' :  '+';  
    $tz = (int) ($tz/ 3600)* 100 +  ($tz% 3600)/ 60;  
    $result =  sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz);  
   * Returns the server hostname or 'localhost.localdomain' if unknown.  
  private function ServerHostname() {  
    } elseif (isset ($_SERVER['SERVER_NAME'])) {  
      $result =  $_SERVER['SERVER_NAME'];  
      $result =  'localhost.localdomain';  
   * Returns a message in the appropriate language.  
  private function Lang($key) {  
      return 'Language string failed to load: ' .  $key;  
   * Returns true if an error occurred.  
    return ($this->error_count >  0);  
   * Changes every end of line from CR or LF to CRLF.  
  private function FixEOL($str) {  
    $this->CustomHeader[] =  explode(':', $custom_header, 2);  
   * Evaluates the message and returns modifications for inline images and backgrounds  
  public function MsgHTML($message, $basedir =  '') {  
      foreach($images[2] as $i =>  $url) {  
        // do not change urls for absolute images (thanks to corvuscorax)  
          ($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);  
    if (!empty($textMsg) &&  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  
   * @return string MIME type of ext  
      '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',  
      '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',  
      'rtx'   =>   'text/richtext',  
      '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'  
   * Set (or reset) Class Objects (variables)  
   * $page->set('X-Priority', '3');  
   * @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 =  '') {  
      if (isset ($this->$name) ) {  
      if ($e->getCode() ==  self::STOP_CRITICAL) {  
   * Strips newlines to prevent header injection.  
   * @param string $str String  
   * Set the private key file and password to sign the message.  
   * @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.  
   * @param string $key_filename Parameter File Name  
   * @param string $key_pass Password for private key  
    for ($i= 0;$i< strlen($txt);$i++ ) {  
      if ( ((0x21 <=  $ord) &&  ($ord <=  0x3A)) ||  $ord ==  0x3C ||  ((0x3E <=  $ord) &&  ($ord <=  0x7E)) ) {  
   * Generate DKIM signature  
   * @param string $s Header  
    if ($this->DKIM_passphrase!= '') {  
   * Generate DKIM Canonicalization Header  
   * @param string $s Header  
    foreach ($lines as $key=> $line) {  
      list ($heading,$value)= explode(":",$line,2); 
      $value= preg_replace("/\s+/"," ",$value) ; // Compress useless spaces  
      $lines[$key]= $heading. ":". trim($value) ; // Don't forget to remove WSP around the value  
   * Generate DKIM Canonicalization Body  
   * @param string $body Message Body  
    if ($body ==  '') return "\r\n";  
    // stabilize line endings  
    // END stabilize line endings  
   * Create the DKIM header, body, as new header  
   * @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) {  
      } elseif (strpos($header,'To:') ===  0) {  
    $subject  =  str_replace('|','=7C',$this->DKIM_QP($subject_header)) ; // Copied header fields (dkim-quoted-printable  
    $DKIMlen  =  strlen($body) ; // Length of body  
    $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".   
                "\tbh=" .  $DKIMb64 .  ";\r\n".   
    $toSign   =  $this->DKIM_HeaderC($from_header .  "\r\n" .  $to_header .  "\r\n" .  $subject_header .  "\r\n" .  $dkimhdrs);  
    return "X-PHPMAILER-DKIM: phpmailer.worxware.com\r\n". $dkimhdrs. $signed. "\r\n";  
  protected function doCallback($isSent,$to,$cc,$bcc,$subject,$body) {  
      $params =  array($isSent,$to,$cc,$bcc,$subject,$body);  
    $errorMsg =  '<strong>' .  $this->getMessage() .  "</strong><br />\n";  
 
 
        
       |