File: 1.13.3b/server/base/phpmailer/class.phpmailer.php (View as HTML)

  1: <?php
  2: /*~ class.phpmailer.php
  3: .---------------------------------------------------------------------------.
  4: |  Software: PHPMailer - PHP email class                                    |
  5: |   Version: 5.0.0                                                          |
  6: |   Contact: via sourceforge.net support pages (also www.codeworxtech.com)  |
  7: |      Info: http://phpmailer.sourceforge.net                               |
  8: |   Support: http://sourceforge.net/projects/phpmailer/                     |
  9: | ------------------------------------------------------------------------- |
 10: |     Admin: Andy Prevost (project admininistrator)                         |
 11: |   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
 12: |          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |
 13: |   Founder: Brent R. Matzelle (original founder)                           |
 14: | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |
 15: | Copyright (c) 2001-2003, Brent R. Matzelle                                |
 16: | ------------------------------------------------------------------------- |
 17: |   License: Distributed under the Lesser General Public License (LGPL)     |
 18: |            http://www.gnu.org/copyleft/lesser.html                        |
 19: | This program is distributed in the hope that it will be useful - WITHOUT  |
 20: | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
 21: | FITNESS FOR A PARTICULAR PURPOSE.                                         |
 22: | ------------------------------------------------------------------------- |
 23: | We offer a number of paid services (www.codeworxtech.com):                |
 24: | - Web Hosting on highly optimized fast and secure servers                 |
 25: | - Technology Consulting                                                   |
 26: | - Oursourcing (highly qualified programmers and graphic designers)        |
 27: '---------------------------------------------------------------------------'
 28: */
 29: 
 30: /**
 31:  * PHPMailer - PHP email transport class
 32:  * NOTE: Requires PHP version 5 or later
 33:  * @package PHPMailer
 34:  * @author Andy Prevost
 35:  * @author Marcus Bointon
 36:  * @copyright 2004 - 2009 Andy Prevost
 37:  * @version $Id: class.phpmailer.php 254 2009-04-02 18:52:18Z codeworxtech $
 38:  * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
 39:  */
 40: 
 41: if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n");
 42: 
 43: class PHPMailer {
 44: 
 45:   /////////////////////////////////////////////////
 46:   // PROPERTIES, PUBLIC
 47:   /////////////////////////////////////////////////
 48: 
 49:   /**
 50:    * Email priority (1 = High, 3 = Normal, 5 = low).
 51:    * @var int
 52:    */
 53:   public $Priority          = 3;
 54: 
 55:   /**
 56:    * Sets the CharSet of the message.
 57:    * @var string
 58:    */
 59:   public $CharSet           = 'iso-8859-1';
 60: 
 61:   /**
 62:    * Sets the Content-type of the message.
 63:    * @var string
 64:    */
 65:   public $ContentType       = 'text/plain';
 66: 
 67:   /**
 68:    * Sets the Encoding of the message. Options for this are
 69:    *  "8bit", "7bit", "binary", "base64", and "quoted-printable".
 70:    * @var string
 71:    */
 72:   public $Encoding          = '8bit';
 73: 
 74:   /**
 75:    * Holds the most recent mailer error message.
 76:    * @var string
 77:    */
 78:   public $ErrorInfo         = '';
 79: 
 80:   /**
 81:    * Sets the From email address for the message.
 82:    * @var string
 83:    */
 84:   public $From              = 'root@localhost';
 85: 
 86:   /**
 87:    * Sets the From name of the message.
 88:    * @var string
 89:    */
 90:   public $FromName          = 'Root User';
 91: 
 92:   /**
 93:    * Sets the Sender email (Return-Path) of the message.  If not empty,
 94:    * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
 95:    * @var string
 96:    */
 97:   public $Sender            = '';
 98: 
 99:   /**
100:    * Sets the Subject of the message.
101:    * @var string
102:    */
103:   public $Subject           = '';
104: 
105:   /**
106:    * Sets the Body of the message.  This can be either an HTML or text body.
107:    * If HTML then run IsHTML(true).
108:    * @var string
109:    */
110:   public $Body              = '';
111: 
112:   /**
113:    * Sets the text-only body of the message.  This automatically sets the
114:    * email to multipart/alternative.  This body can be read by mail
115:    * clients that do not have HTML email capability such as mutt. Clients
116:    * that can read HTML will view the normal Body.
117:    * @var string
118:    */
119:   public $AltBody           = '';
120: 
121:   /**
122:    * Sets word wrapping on the body of the message to a given number of
123:    * characters.
124:    * @var int
125:    */
126:   public $WordWrap          = 0;
127: 
128:   /**
129:    * Method to send mail: ("mail", "sendmail", or "smtp").
130:    * @var string
131:    */
132:   public $Mailer            = 'mail';
133: 
134:   /**
135:    * Sets the path of the sendmail program.
136:    * @var string
137:    */
138:   public $Sendmail          = '/usr/sbin/sendmail';
139: 
140:   /**
141:    * Path to PHPMailer plugins.  Useful if the SMTP class
142:    * is in a different directory than the PHP include path.
143:    * @var string
144:    */
145:   public $PluginDir         = '';
146: 
147:   /**
148:    * Sets the email address that a reading confirmation will be sent.
149:    * @var string
150:    */
151:   public $ConfirmReadingTo  = '';
152: 
153:   /**
154:    * Sets the hostname to use in Message-Id and Received headers
155:    * and as default HELO string. If empty, the value returned
156:    * by SERVER_NAME is used or 'localhost.localdomain'.
157:    * @var string
158:    */
159:   public $Hostname          = '';
160: 
161:   /**
162:    * Sets the message ID to be used in the Message-Id header.
163:    * If empty, a unique id will be generated.
164:    * @var string
165:    */
166:   public $MessageID         = '';
167: 
168:   /////////////////////////////////////////////////
169:   // PROPERTIES FOR SMTP
170:   /////////////////////////////////////////////////
171: 
172:   /**
173:    * Sets the SMTP hosts.  All hosts must be separated by a
174:    * semicolon.  You can also specify a different port
175:    * for each host by using this format: [hostname:port]
176:    * (e.g. "smtp1.example.com:25;smtp2.example.com").
177:    * Hosts will be tried in order.
178:    * @var string
179:    */
180:   public $Host          = 'localhost';
181: 
182:   /**
183:    * Sets the default SMTP server port.
184:    * @var int
185:    */
186:   public $Port          = 25;
187: 
188:   /**
189:    * Sets the SMTP HELO of the message (Default is $Hostname).
190:    * @var string
191:    */
192:   public $Helo          = '';
193: 
194:   /**
195:    * Sets connection prefix.
196:    * Options are "", "ssl" or "tls"
197:    * @var string
198:    */
199:   public $SMTPSecure    = '';
200: 
201:   /**
202:    * Sets SMTP authentication. Utilizes the Username and Password variables.
203:    * @var bool
204:    */
205:   public $SMTPAuth      = false;
206: 
207:   /**
208:    * Sets SMTP username.
209:    * @var string
210:    */
211:   public $Username      = '';
212: 
213:   /**
214:    * Sets SMTP password.
215:    * @var string
216:    */
217:   public $Password      = '';
218: 
219:   /**
220:    * Sets the SMTP server timeout in seconds.
221:    * This function will not work with the win32 version.
222:    * @var int
223:    */
224:   public $Timeout       = 10;
225: 
226:   /**
227:    * Sets SMTP class debugging on or off.
228:    * @var bool
229:    */
230:   public $SMTPDebug     = false;
231: 
232:   /**
233:    * Prevents the SMTP connection from being closed after each mail
234:    * sending.  If this is set to true then to close the connection
235:    * requires an explicit call to SmtpClose().
236:    * @var bool
237:    */
238:   public $SMTPKeepAlive = false;
239: 
240:   /**
241:    * Provides the ability to have the TO field process individual
242:    * emails, instead of sending to entire TO addresses
243:    * @var bool
244:    */
245:   public $SingleTo      = false;
246: 
247:   /**
248:    * Provides the ability to change the line ending
249:    * @var string
250:    */
251:   public $LE              = "\n";
252: 
253:   /////////////////////////////////////////////////
254:   // PROPERTIES, PRIVATE AND PROTECTED
255:   /////////////////////////////////////////////////
256: 
257:   private   $smtp           = NULL;
258:   private   $to             = array();
259:   private   $cc             = array();
260:   private   $bcc            = array();
261:   private   $ReplyTo        = array();
262:   private   $all_recipients = array();
263:   private   $attachment     = array();
264:   private   $CustomHeader   = array();
265:   private   $message_type   = '';
266:   private   $boundary       = array();
267:   protected $language       = array();
268:   private   $error_count    = 0;
269:   private   $sign_cert_file = "";
270:   private   $sign_key_file  = "";
271:   private   $sign_key_pass  = "";
272:   private   $exceptions     = false;
273: 
274:   /////////////////////////////////////////////////
275:   // CONSTANTS
276:   /////////////////////////////////////////////////
277: 
278:   const VERSION = '5.0.0';
279:   const STOP_MESSAGE = 0; // message only, continue processing
280:   const STOP_CONTINUE = 1; // message?, likely ok to continue processing
281:   const STOP_CRITICAL = 2; // message, plus full stop, critical error reached
282: 
283:   /////////////////////////////////////////////////
284:   // METHODS, VARIABLES
285:   /////////////////////////////////////////////////
286: 
287:   /**
288:    * Constructor
289:    * @param boolean $exceptions Should we throw external exceptions?
290:    */
291:   public function __construct($exceptions = false) {
292:     $this->exceptions = ($exceptions == true);
293:   }
294: 
295:   /**
296:    * Sets message type to HTML.
297:    * @param bool $ishtml
298:    * @return void
299:    */
300:   public function IsHTML($ishtml = true) {
301:     if ($ishtml) {
302:       $this->ContentType = 'text/html';
303:     } else {
304:       $this->ContentType = 'text/plain';
305:     }
306:   }
307: 
308:   /**
309:    * Sets Mailer to send message using SMTP.
310:    * @return void
311:    */
312:   public function IsSMTP() {
313:     $this->Mailer = 'smtp';
314:   }
315: 
316:   /**
317:    * Sets Mailer to send message using PHP mail() function.
318:    * @return void
319:    */
320:   public function IsMail() {
321:     $this->Mailer = 'mail';
322:   }
323: 
324:   /**
325:    * Sets Mailer to send message using the $Sendmail program.
326:    * @return void
327:    */
328:   public function IsSendmail() {
329:     if (!stristr(ini_get('sendmail_path'), 'sendmail')) {
330:       $this->Sendmail = '/var/qmail/bin/sendmail';
331:     }
332:     $this->Mailer = 'sendmail';
333:   }
334: 
335:   /**
336:    * Sets Mailer to send message using the qmail MTA.
337:    * @return void
338:    */
339:   public function IsQmail() {
340:     if (stristr(ini_get('sendmail_path'), 'qmail')) {
341:       $this->Sendmail = '/var/qmail/bin/sendmail';
342:     }
343:     $this->Mailer = 'sendmail';
344:   }
345: 
346:   /////////////////////////////////////////////////
347:   // METHODS, RECIPIENTS
348:   /////////////////////////////////////////////////
349: 
350:   /**
351:    * Adds a "To" address.
352:    * @param string $address
353:    * @param string $name
354:    * @return boolean true on success, false if address already used
355:    */
356:   public function AddAddress($address, $name = '') {
357:     return $this->AddAnAddress('to', $address, $name);
358:   }
359: 
360:   /**
361:    * Adds a "Cc" address.
362:    * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
363:    * @param string $address
364:    * @param string $name
365:    * @return boolean true on success, false if address already used
366:    */
367:   public function AddCC($address, $name = '') {
368:     return $this->AddAnAddress('cc', $address, $name);
369:   }
370: 
371:   /**
372:    * Adds a "Bcc" address.
373:    * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
374:    * @param string $address
375:    * @param string $name
376:    * @return boolean true on success, false if address already used
377:    */
378:   public function AddBCC($address, $name = '') {
379:     return $this->AddAnAddress('bcc', $address, $name);
380:   }
381: 
382:   /**
383:    * Adds a "Reply-to" address.
384:    * @param string $address
385:    * @param string $name
386:    * @return boolean
387:    */
388:   public function AddReplyTo($address, $name = '') {
389:     return $this->AddAnAddress('ReplyTo', $address, $name);
390:   }
391: 
392:   /**
393:    * Adds an address to one of the recipient arrays
394:    * Addresses that have been added already return false, but do not throw exceptions
395:    * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo'
396:    * @param string $address The email address to send to
397:    * @param string $name
398:    * @return boolean true on success, false if address already used or invalid in some way
399:    * @access private
400:    */
401:   private function AddAnAddress($kind, $address, $name = '') {
402:     if (!preg_match('/^(to|cc|bcc|ReplyTo)$/', $kind)) {
403:       echo 'Invalid recipient array: ' . kind;
404:       return false;
405:     }
406:     $address = trim($address);
407:     $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
408:     if (!self::ValidateAddress($address)) {
409:       $this->SetError($this->Lang('invalid_address').': '. $address);
410:       if ($this->exceptions) {
411:         throw new phpmailerException($this->Lang('invalid_address').': '.$address);
412:       }
413:       echo $this->Lang('invalid_address').': '.$address;
414:       return false;
415:     }
416:   if ($kind != 'ReplyTo') {
417:     if (!isset($this->all_recipients[strtolower($address)])) {
418:         array_push($this->$kind, array($address, $name));
419:         $this->all_recipients[strtolower($address)] = true;
420:     return true;
421:       }
422:   } else {
423:     if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
424:         $this->ReplyTo[strtolower($address)] = array($address, $name);
425:     return true;
426:     }
427:   }
428:     return false;
429:   }
430: 
431: /**
432:  * Set the From and FromName properties
433:  * @param string $address
434:  * @param string $name
435:  * @return boolean
436:  */
437:   public function SetFrom($address, $name = '') {
438:     $address = trim($address);
439:     $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
440:     if (!self::ValidateAddress($address)) {
441:       $this->SetError($this->Lang('invalid_address').': '. $address);
442:       if ($this->exceptions) {
443:         throw new phpmailerException($this->Lang('invalid_address').': '.$address);
444:       }
445:       echo $this->Lang('invalid_address').': '.$address;
446:       return false;
447:     }
448:   $this->From = $address;
449:   $this->FromName = $name;
450:   return true;
451:   }
452: 
453:   /**
454:    * Check that a string looks roughly like an email address should
455:    * Static so it can be used without instantiation
456:    * Tries to use PHP built-in validator in the filter extension (from PHP 5.2), falls back to a reasonably competent regex validator
457:    * Conforms approximately to RFC2822
458:    * @link http://www.hexillion.com/samples/#Regex Original pattern found here
459:    * @param string $address The email address to check
460:    * @return boolean
461:    * @static
462:    * @access public
463:    */
464:   public static function ValidateAddress($address) {
465:     if (function_exists('filter_var')) { //Introduced in PHP 5.2
466:       if(filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) {
467:         return false;
468:       } else {
469:         return true;
470:       }
471:     } else {
472:       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);
473:     }
474:   }
475: 
476:   /////////////////////////////////////////////////
477:   // METHODS, MAIL SENDING
478:   /////////////////////////////////////////////////
479: 
480:   /**
481:    * Creates message and assigns Mailer. If the message is
482:    * not sent successfully then it returns false.  Use the ErrorInfo
483:    * variable to view description of the error.
484:    * @return bool
485:    */
486:   public function Send() {
487:     try {
488:       if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
489:         throw new phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL);
490:       }
491: 
492:       // Set whether the message is multipart/alternative
493:       if(!empty($this->AltBody)) {
494:         $this->ContentType = 'multipart/alternative';
495:       }
496: 
497:       $this->error_count = 0; // reset errors
498:       $this->SetMessageType();
499:       $header = $this->CreateHeader();
500:       $body = $this->CreateBody();
501: 
502:       if (empty($this->Body)) {
503:         throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL);
504:       }
505: 
506:       // Choose the mailer and send through it
507:       switch($this->Mailer) {
508:         case 'sendmail':
509:           return $this->SendmailSend($header, $body);
510:         case 'smtp':
511:           return $this->SmtpSend($header, $body);
512:         case 'mail':
513:         default:
514:           return $this->MailSend($header, $body);
515:       }
516: 
517:     } catch (phpmailerException $e) {
518:       $this->SetError($e->getMessage());
519:       if ($this->exceptions) {
520:         throw $e;
521:       }
522:       echo $e->getMessage()."\n";
523:       return false;
524:     }
525:   }
526: 
527:   /**
528:    * Sends mail using the $Sendmail program.
529:    * @param string $header The message headers
530:    * @param string $body The message body
531:    * @access protected
532:    * @return bool
533:    */
534:   protected function SendmailSend($header, $body) {
535:     if ($this->Sender != '') {
536:       $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
537:     } else {
538:       $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
539:     }
540:     if(!@$mail = popen($sendmail, 'w')) {
541:       throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
542:     }
543:     fputs($mail, $header);
544:     fputs($mail, $body);
545:     $result = pclose($mail);
546:     if($result != 0) {
547:       throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
548:     }
549:     return true;
550:   }
551: 
552:   /**
553:    * Sends mail using the PHP mail() function.
554:    * @param string $header The message headers
555:    * @param string $body The message body
556:    * @access protected
557:    * @return bool
558:    */
559:   protected function MailSend($header, $body) {
560:     $toArr = array();
561:     foreach($this->to as $t) {
562:       $toArr[] = $this->AddrFormat($t);
563:     }
564:     $to = implode(', ', $toArr);
565: 
566:     $params = sprintf("-oi -f %s", $this->Sender);
567:     if ($this->Sender != '' && strlen(ini_get('safe_mode'))< 1) {
568:       $old_from = ini_get('sendmail_from');
569:       ini_set('sendmail_from', $this->Sender);
570:       if ($this->SingleTo === true && count($toArr) > 1) {
571:         foreach ($toArr as $key => $val) {
572:           $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
573:         }
574:       } else {
575:         $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
576:       }
577:     } else {
578:       if ($this->SingleTo === true && count($toArr) > 1) {
579:         foreach ($toArr as $key => $val) {
580:           $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
581:         }
582:       } else {
583:         $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header);
584:       }
585:     }
586:     if (isset($old_from)) {
587:       ini_set('sendmail_from', $old_from);
588:     }
589:     if(!$rt) {
590:       throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL);
591:     }
592:     return true;
593:   }
594: 
595:   /**
596:    * Sends mail via SMTP using PhpSMTP
597:    * Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
598:    * @param string $header The message headers
599:    * @param string $body The message body
600:    * @uses SMTP
601:    * @access protected
602:    * @return bool
603:    */
604:   protected function SmtpSend($header, $body) {
605:     require_once $this->PluginDir . 'class.smtp.php';
606:     $bad_rcpt = array();
607: 
608:     if(!$this->SmtpConnect()) {
609:       throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL);
610:     }
611:     $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
612:     if(!$this->smtp->Mail($smtp_from)) {
613:       throw new phpmailerException($this->Lang('from_failed') . $smtp_from, self::STOP_CRITICAL);
614:     }
615: 
616:     // Attempt to send attach all recipients
617:     foreach($this->to as $to) {
618:       if (!$this->smtp->Recipient($to[0])) {
619:         $bad_rcpt[] = $to[0];
620:       }
621:     }
622:     foreach($this->cc as $cc) {
623:       if (!$this->smtp->Recipient($cc[0])) {
624:         $bad_rcpt[] = $cc[0];
625:       }
626:     }
627:     foreach($this->bcc as $bcc) {
628:       if (!$this->smtp->Recipient($bcc[0])) {
629:         $bad_rcpt[] = $bcc[0];
630:       }
631:     }
632:     if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses
633:       $badaddresses = implode(', ', $bad_rcpt);
634:       throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses);
635:     }
636:     if(!$this->smtp->Data($header . $body)) {
637:       throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL);
638:     }
639:     if($this->SMTPKeepAlive == true) {
640:       $this->smtp->Reset();
641:     }
642:     return true;
643:   }
644: 
645:   /**
646:    * Initiates a connection to an SMTP server.
647:    * Returns false if the operation failed.
648:    * @uses SMTP
649:    * @access public
650:    * @return bool
651:    */
652:   public function SmtpConnect() {
653:     if(is_null($this->smtp)) {
654:       $this->smtp = new SMTP();
655:     }
656: 
657:     $this->smtp->do_debug = $this->SMTPDebug;
658:     $hosts = explode(';', $this->Host);
659:     $index = 0;
660:     $connection = $this->smtp->Connected();
661: 
662:     // Retry while there is no connection
663:     try {
664:       while($index < count($hosts) && !$connection) {
665:         $hostinfo = array();
666:         if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) {
667:           $host = $hostinfo[1];
668:           $port = $hostinfo[2];
669:         } else {
670:           $host = $hosts[$index];
671:           $port = $this->Port;
672:         }
673: 
674:         $tls = ($this->SMTPSecure == 'tls');
675:         $ssl = ($this->SMTPSecure == 'ssl');
676: 
677:         if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) {
678: 
679:           $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname());
680:           $this->smtp->Hello($hello);
681: 
682:           if ($tls) {
683:             if (!$this->smtp->StartTLS()) {
684:               throw new phpmailerException($this->Lang('tls'));
685:             }
686: 
687:             //We must resend HELO after tls negotiation
688:             $this->smtp->Hello($hello);
689:           }
690: 
691:           $connection = true;
692:           if ($this->SMTPAuth) {
693:             if (!$this->smtp->Authenticate($this->Username, $this->Password)) {
694:               throw new phpmailerException($this->Lang('authenticate'));
695:             }
696:           }
697:         }
698:         $index++;
699:         if (!$connection) {
700:           throw new phpmailerException($this->Lang('connect_host'));
701:         }
702:       }
703:     } catch (phpmailerException $e) {
704:       $this->smtp->Reset();
705:       throw $e;
706:     }
707:     return true;
708:   }
709: 
710:   /**
711:    * Closes the active SMTP session if one exists.
712:    * @return void
713:    */
714:   public function SmtpClose() {
715:     if(!is_null($this->smtp)) {
716:       if($this->smtp->Connected()) {
717:         $this->smtp->Quit();
718:         $this->smtp->Close();
719:       }
720:     }
721:   }
722: 
723:   /**
724:   * Sets the language for all class error messages.
725:   * Returns false if it cannot load the language file.  The default language is English.
726:   * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br")
727:   * @param string $lang_path Path to the language file directory
728:   * @access public
729:   */
730:   function SetLanguage($langcode = 'en', $lang_path = 'language/') {
731:     //Define full set of translatable strings
732:     $PHPMAILER_LANG = array(
733:       'provide_address' => 'You must provide at least one recipient email address.',
734:       'mailer_not_supported' => ' mailer is not supported.',
735:       'execute' => 'Could not execute: ',
736:       'instantiate' => 'Could not instantiate mail function.',
737:       'authenticate' => 'SMTP Error: Could not authenticate.',
738:       'from_failed' => 'The following From address failed: ',
739:       'recipients_failed' => 'SMTP Error: The following recipients failed: ',
740:       'data_not_accepted' => 'SMTP Error: Data not accepted.',
741:       'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
742:       'file_access' => 'Could not access file: ',
743:       'file_open' => 'File Error: Could not open file: ',
744:       'encoding' => 'Unknown encoding: ',
745:       'signing' => 'Signing Error: ',
746:       'smtp_error' => 'SMTP server error: ',
747:       'empty_message' => 'Message body empty',
748:       'invalid_address' => 'Invalid address',
749:       'variable_set' => 'Cannot set or reset variable: '
750:     );
751:     //Overwrite language-specific strings. This way we'll never have missing translations - no more "language string failed to load"!
752:     $l = true;
753:     if ($langcode != 'en') { //There is no English translation file
754:       $l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php';
755:     }
756:     $this->language = $PHPMAILER_LANG;
757:     return ($l == true); //Returns false if language not found
758:   }
759: 
760:   /**
761:   * Return the current array of language strings
762:   * @return array
763:   */
764:   public function GetTranslations() {
765:     return $this->language;
766:   }
767: 
768:   /////////////////////////////////////////////////
769:   // METHODS, MESSAGE CREATION
770:   /////////////////////////////////////////////////
771: 
772:   /**
773:    * Creates recipient headers.
774:    * @access public
775:    * @return string
776:    */
777:   public function AddrAppend($type, $addr) {
778:     $addr_str = $type . ': ';
779:     $addresses = array();
780:     foreach ($addr as $a) {
781:       $addresses[] = $this->AddrFormat($a);
782:     }
783:     $addr_str .= implode(', ', $addresses);
784:     $addr_str .= $this->LE;
785: 
786:     return $addr_str;
787:   }
788: 
789:   /**
790:    * Formats an address correctly.
791:    * @access public
792:    * @return string
793:    */
794:   public function AddrFormat($addr) {
795:     if (empty($addr[1])) {
796:       return $this->SecureHeader($addr[0]);
797:     } else {
798:       return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
799:     }
800:   }
801: 
802:   /**
803:    * Wraps message for use with mailers that do not
804:    * automatically perform wrapping and for quoted-printable.
805:    * Original written by philippe.
806:    * @param string $message The message to wrap
807:    * @param integer $length The line length to wrap to
808:    * @param boolean $qp_mode Whether to run in Quoted-Printable mode
809:    * @access public
810:    * @return string
811:    */
812:   public function WrapText($message, $length, $qp_mode = false) {
813:     $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
814:     // If utf-8 encoding is used, we will need to make sure we don't
815:     // split multibyte characters when we wrap
816:     $is_utf8 = (strtolower($this->CharSet) == "utf-8");
817: 
818:     $message = $this->FixEOL($message);
819:     if (substr($message, -1) == $this->LE) {
820:       $message = substr($message, 0, -1);
821:     }
822: 
823:     $line = explode($this->LE, $message);
824:     $message = '';
825:     for ($i=0 ;$i < count($line); $i++) {
826:       $line_part = explode(' ', $line[$i]);
827:       $buf = '';
828:       for ($e = 0; $e<count($line_part); $e++) {
829:         $word = $line_part[$e];
830:         if ($qp_mode and (strlen($word) > $length)) {
831:           $space_left = $length - strlen($buf) - 1;
832:           if ($e != 0) {
833:             if ($space_left > 20) {
834:               $len = $space_left;
835:               if ($is_utf8) {
836:                 $len = $this->UTF8CharBoundary($word, $len);
837:               } elseif (substr($word, $len - 1, 1) == "=") {
838:                 $len--;
839:               } elseif (substr($word, $len - 2, 1) == "=") {
840:                 $len -= 2;
841:               }
842:               $part = substr($word, 0, $len);
843:               $word = substr($word, $len);
844:               $buf .= ' ' . $part;
845:               $message .= $buf . sprintf("=%s", $this->LE);
846:             } else {
847:               $message .= $buf . $soft_break;
848:             }
849:             $buf = '';
850:           }
851:           while (strlen($word) > 0) {
852:             $len = $length;
853:             if ($is_utf8) {
854:               $len = $this->UTF8CharBoundary($word, $len);
855:             } elseif (substr($word, $len - 1, 1) == "=") {
856:               $len--;
857:             } elseif (substr($word, $len - 2, 1) == "=") {
858:               $len -= 2;
859:             }
860:             $part = substr($word, 0, $len);
861:             $word = substr($word, $len);
862: 
863:             if (strlen($word) > 0) {
864:               $message .= $part . sprintf("=%s", $this->LE);
865:             } else {
866:               $buf = $part;
867:             }
868:           }
869:         } else {
870:           $buf_o = $buf;
871:           $buf .= ($e == 0) ? $word : (' ' . $word);
872: 
873:           if (strlen($buf) > $length and $buf_o != '') {
874:             $message .= $buf_o . $soft_break;
875:             $buf = $word;
876:           }
877:         }
878:       }
879:       $message .= $buf . $this->LE;
880:     }
881: 
882:     return $message;
883:   }
884: 
885:   /**
886:    * Finds last character boundary prior to maxLength in a utf-8
887:    * quoted (printable) encoded string.
888:    * Original written by Colin Brown.
889:    * @access public
890:    * @param string $encodedText utf-8 QP text
891:    * @param int    $maxLength   find last character boundary prior to this length
892:    * @return int
893:    */
894:   public function UTF8CharBoundary($encodedText, $maxLength) {
895:     $foundSplitPos = false;
896:     $lookBack = 3;
897:     while (!$foundSplitPos) {
898:       $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
899:       $encodedCharPos = strpos($lastChunk, "=");
900:       if ($encodedCharPos !== false) {
901:         // Found start of encoded character byte within $lookBack block.
902:         // Check the encoded byte value (the 2 chars after the '=')
903:         $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
904:         $dec = hexdec($hex);
905:         if ($dec < 128) { // Single byte character.
906:           // If the encoded char was found at pos 0, it will fit
907:           // otherwise reduce maxLength to start of the encoded char
908:           $maxLength = ($encodedCharPos == 0) ? $maxLength :
909:           $maxLength - ($lookBack - $encodedCharPos);
910:           $foundSplitPos = true;
911:         } elseif ($dec >= 192) { // First byte of a multi byte character
912:           // Reduce maxLength to split at start of character
913:           $maxLength = $maxLength - ($lookBack - $encodedCharPos);
914:           $foundSplitPos = true;
915:         } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back
916:           $lookBack += 3;
917:         }
918:       } else {
919:         // No encoded character found
920:         $foundSplitPos = true;
921:       }
922:     }
923:     return $maxLength;
924:   }
925: 
926: 
927:   /**
928:    * Set the body wrapping.
929:    * @access public
930:    * @return void
931:    */
932:   public function SetWordWrap() {
933:     if($this->WordWrap < 1) {
934:       return;
935:     }
936: 
937:     switch($this->message_type) {
938:       case 'alt':
939:       case 'alt_attachments':
940:         $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
941:         break;
942:       default:
943:         $this->Body = $this->WrapText($this->Body, $this->WordWrap);
944:         break;
945:     }
946:   }
947: 
948:   /**
949:    * Assembles message header.
950:    * @access public
951:    * @return string The assembled header
952:    */
953:   public function CreateHeader() {
954:     $result = '';
955: 
956:     // Set the boundaries
957:     $uniq_id = md5(uniqid(time()));
958:     $this->boundary[1] = 'b1_' . $uniq_id;
959:     $this->boundary[2] = 'b2_' . $uniq_id;
960: 
961:     $result .= $this->HeaderLine('Date', self::RFCDate());
962:     if($this->Sender == '') {
963:       $result .= $this->HeaderLine('Return-Path', trim($this->From));
964:     } else {
965:       $result .= $this->HeaderLine('Return-Path', trim($this->Sender));
966:     }
967: 
968:     // To be created automatically by mail()
969:     if($this->Mailer != 'mail') {
970:       if(count($this->to) > 0) {
971:         $result .= $this->AddrAppend('To', $this->to);
972:       } elseif (count($this->cc) == 0) {
973:         $result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
974:       }
975:     }
976: 
977:     $from = array();
978:     $from[0][0] = trim($this->From);
979:     $from[0][1] = $this->FromName;
980:     $result .= $this->AddrAppend('From', $from);
981: 
982:     // sendmail and mail() extract Cc from the header before sending
983:     if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->cc) > 0)) {
984:       $result .= $this->AddrAppend('Cc', $this->cc);
985:     }
986: 
987:     // sendmail and mail() extract Bcc from the header before sending
988:     if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
989:       $result .= $this->AddrAppend('Bcc', $this->bcc);
990:     }
991: 
992:     if(count($this->ReplyTo) > 0) {
993:       $result .= $this->AddrAppend('Reply-to', $this->ReplyTo);
994:     }
995: 
996:     // mail() sets the subject itself
997:     if($this->Mailer != 'mail') {
998:       $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
999:     }
1000: 
1001:     if($this->MessageID != '') {
1002:       $result .= $this->HeaderLine('Message-ID',$this->MessageID);
1003:     } else {
1004:       $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
1005:     }
1006:     $result .= $this->HeaderLine('X-Priority', $this->Priority);
1007:     $result .= $this->HeaderLine('X-Mailer', 'PHPMailer ' . self::VERSION . ' (phpmailer.codeworxtech.com)');
1008: 
1009:     if($this->ConfirmReadingTo != '') {
1010:       $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
1011:     }
1012: 
1013:     // Add custom headers
1014:     for($index = 0; $index < count($this->CustomHeader); $index++) {
1015:       $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1])));
1016:     }
1017:     if (!$this->sign_key_file) {
1018:       $result .= $this->HeaderLine('MIME-Version', '1.0');
1019:       $result .= $this->GetMailMIME();
1020:     }
1021: 
1022:     return $result;
1023:   }
1024: 
1025:   /**
1026:    * Returns the message MIME.
1027:    * @access public
1028:    * @return string
1029:    */
1030:   public function GetMailMIME() {
1031:     $result = '';
1032:     switch($this->message_type) {
1033:       case 'plain':
1034:         $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
1035:         $result .= sprintf("Content-Type: %s; charset=\"%s\"", $this->ContentType, $this->CharSet);
1036:         break;
1037:       case 'attachments':
1038:       case 'alt_attachments':
1039:         if($this->InlineImageExists()){
1040:           $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE);
1041:         } else {
1042:           $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');
1043:           $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
1044:         }
1045:         break;
1046:       case 'alt':
1047:         $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
1048:         $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
1049:         break;
1050:     }
1051: 
1052:     if($this->Mailer != 'mail') {
1053:       $result .= $this->LE.$this->LE;
1054:     }
1055: 
1056:     return $result;
1057:   }
1058: 
1059:   /**
1060:    * Assembles the message body.  Returns an empty string on failure.
1061:    * @access public
1062:    * @return string The assembled message body
1063:    */
1064:   public function CreateBody() {
1065:     $body = '';
1066: 
1067:     if ($this->sign_key_file) {
1068:       $body .= $this->GetMailMIME();
1069:     }
1070: 
1071:     $this->SetWordWrap();
1072: 
1073:     switch($this->message_type) {
1074:       case 'alt':
1075:         $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
1076:         $body .= $this->EncodeString($this->AltBody, $this->Encoding);
1077:         $body .= $this->LE.$this->LE;
1078:         $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
1079:         $body .= $this->EncodeString($this->Body, $this->Encoding);
1080:         $body .= $this->LE.$this->LE;
1081:         $body .= $this->EndBoundary($this->boundary[1]);
1082:         break;
1083:       case 'plain':
1084:         $body .= $this->EncodeString($this->Body, $this->Encoding);
1085:         break;
1086:       case 'attachments':
1087:         $body .= $this->GetBoundary($this->boundary[1], '', '', '');
1088:         $body .= $this->EncodeString($this->Body, $this->Encoding);
1089:         $body .= $this->LE;
1090:         $body .= $this->AttachAll();
1091:         break;
1092:       case 'alt_attachments':
1093:         $body .= sprintf("--%s%s", $this->boundary[1], $this->LE);
1094:         $body .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE);
1095:         $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body
1096:         $body .= $this->EncodeString($this->AltBody, $this->Encoding);
1097:         $body .= $this->LE.$this->LE;
1098:         $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body
1099:         $body .= $this->EncodeString($this->Body, $this->Encoding);
1100:         $body .= $this->LE.$this->LE;
1101:         $body .= $this->EndBoundary($this->boundary[2]);
1102:         $body .= $this->AttachAll();
1103:         break;
1104:     }
1105: 
1106:     if ($this->IsError()) {
1107:       $body = '';
1108:     } elseif ($this->sign_key_file) {
1109:       try {
1110:         $file = tempnam('', 'mail');
1111:         file_put_contents($file, $body); //TODO check this worked
1112:         $signed = tempnam("", "signed");
1113:         if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) {
1114:           @unlink($file);
1115:           @unlink($signed);
1116:           $body = file_get_contents($signed);
1117:         } else {
1118:           @unlink($file);
1119:           @unlink($signed);
1120:           throw new phpmailerException($this->Lang("signing").openssl_error_string());
1121:         }
1122:       } catch (phpmailerException $e) {
1123:         $body = '';
1124:         if ($this->exceptions) {
1125:           throw $e;
1126:         }
1127:       }
1128:     }
1129: 
1130:     return $body;
1131:   }
1132: 
1133:   /**
1134:    * Returns the start of a message boundary.
1135:    * @access private
1136:    */
1137:   private function GetBoundary($boundary, $charSet, $contentType, $encoding) {
1138:     $result = '';
1139:     if($charSet == '') {
1140:       $charSet = $this->CharSet;
1141:     }
1142:     if($contentType == '') {
1143:       $contentType = $this->ContentType;
1144:     }
1145:     if($encoding == '') {
1146:       $encoding = $this->Encoding;
1147:     }
1148:     $result .= $this->TextLine('--' . $boundary);
1149:     $result .= sprintf("Content-Type: %s; charset = \"%s\"", $contentType, $charSet);
1150:     $result .= $this->LE;
1151:     $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding);
1152:     $result .= $this->LE;
1153: 
1154:     return $result;
1155:   }
1156: 
1157:   /**
1158:    * Returns the end of a message boundary.
1159:    * @access private
1160:    */
1161:   private function EndBoundary($boundary) {
1162:     return $this->LE . '--' . $boundary . '--' . $this->LE;
1163:   }
1164: 
1165:   /**
1166:    * Sets the message type.
1167:    * @access private
1168:    * @return void
1169:    */
1170:   private function SetMessageType() {
1171:     if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) {
1172:       $this->message_type = 'plain';
1173:     } else {
1174:       if(count($this->attachment) > 0) {
1175:         $this->message_type = 'attachments';
1176:       }
1177:       if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) {
1178:         $this->message_type = 'alt';
1179:       }
1180:       if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) {
1181:         $this->message_type = 'alt_attachments';
1182:       }
1183:     }
1184:   }
1185: 
1186:   /**
1187:    *  Returns a formatted header line.
1188:    * @access public
1189:    * @return string
1190:    */
1191:   public function HeaderLine($name, $value) {
1192:     return $name . ': ' . $value . $this->LE;
1193:   }
1194: 
1195:   /**
1196:    * Returns a formatted mail line.
1197:    * @access public
1198:    * @return string
1199:    */
1200:   public function TextLine($value) {
1201:     return $value . $this->LE;
1202:   }
1203: 
1204:   /////////////////////////////////////////////////
1205:   // CLASS METHODS, ATTACHMENTS
1206:   /////////////////////////////////////////////////
1207: 
1208:   /**
1209:    * Adds an attachment from a path on the filesystem.
1210:    * Returns false if the file could not be found
1211:    * or accessed.
1212:    * @param string $path Path to the attachment.
1213:    * @param string $name Overrides the attachment name.
1214:    * @param string $encoding File encoding (see $Encoding).
1215:    * @param string $type File extension (MIME) type.
1216:    * @return bool
1217:    */
1218:   public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
1219:     try {
1220:       if ( !@is_file($path) ) {
1221:         throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE);
1222:       }
1223:       $filename = basename($path);
1224:       if ( $name == '' ) {
1225:         $name = $filename;
1226:       }
1227: 
1228:       $this->attachment[] = array(
1229:         0 => $path,
1230:         1 => $filename,
1231:         2 => $name,
1232:         3 => $encoding,
1233:         4 => $type,
1234:         5 => false,  // isStringAttachment
1235:         6 => 'attachment',
1236:         7 => 0
1237:       );
1238: 
1239:     } catch (phpmailerException $e) {
1240:       $this->SetError($e->getMessage());
1241:       if ($this->exceptions) {
1242:         throw $e;
1243:       }
1244:       echo $e->getMessage()."\n";
1245:       if ( $e->getCode() == self::STOP_CRITICAL ) {
1246:         return false;
1247:       }
1248:     }
1249:     return true;
1250:   }
1251: 
1252:   /**
1253:   * Return the current array of attachments
1254:   * @return array
1255:   */
1256:   public function GetAttachments() {
1257:     return $this->attachment;
1258:   }
1259: 
1260:   /**
1261:    * Attaches all fs, string, and binary attachments to the message.
1262:    * Returns an empty string on failure.
1263:    * @access private
1264:    * @return string
1265:    */
1266:   private function AttachAll() {
1267:     // Return text of body
1268:     $mime = array();
1269:     $cidUniq = array();
1270:     $incl = array();
1271: 
1272:     // Add all attachments
1273:     foreach ($this->attachment as $attachment) {
1274:       // Check for string attachment
1275:       $bString = $attachment[5];
1276:       if ($bString) {
1277:         $string = $attachment[0];
1278:       } else {
1279:         $path = $attachment[0];
1280:       }
1281: 
1282:       if (in_array($attachment[0], $incl)) { continue; }
1283:       $filename    = $attachment[1];
1284:       $name        = $attachment[2];
1285:       $encoding    = $attachment[3];
1286:       $type        = $attachment[4];
1287:       $disposition = $attachment[6];
1288:       $cid         = $attachment[7];
1289:       $incl[]      = $attachment[0];
1290:       if ( isset($cidUniq[$cid]) ) { continue; }
1291:       $cidUniq[$cid] = true;
1292: 
1293:       $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);
1294:       $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE);
1295:       $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
1296: 
1297:       if($disposition == 'inline') {
1298:         $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
1299:       }
1300: 
1301:       $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);
1302: 
1303:       // Encode as string attachment
1304:       if($bString) {
1305:         $mime[] = $this->EncodeString($string, $encoding);
1306:         if($this->IsError()) {
1307:           return '';
1308:         }
1309:         $mime[] = $this->LE.$this->LE;
1310:       } else {
1311:         $mime[] = $this->EncodeFile($path, $encoding);
1312:         if($this->IsError()) {
1313:           return '';
1314:         }
1315:         $mime[] = $this->LE.$this->LE;
1316:       }
1317:     }
1318: 
1319:     $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE);
1320: 
1321:     return join('', $mime);
1322:   }
1323: 
1324:   /**
1325:    * Encodes attachment in requested format.
1326:    * Returns an empty string on failure.
1327:    * @param string $path The full path to the file
1328:    * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
1329:    * @see EncodeFile()
1330:    * @access private
1331:    * @return string
1332:    */
1333:   private function EncodeFile($path, $encoding = 'base64') {
1334:     try {
1335:       if (!is_readable($path)) {
1336:         throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE);
1337:       }
1338:       if (function_exists('get_magic_quotes')) {
1339:         function get_magic_quotes() {
1340:           return false;
1341:         }
1342:       }
1343:       if (PHP_VERSION < 6) {
1344:         $magic_quotes = get_magic_quotes_runtime();
1345:         set_magic_quotes_runtime(0);
1346:       }
1347:       $file_buffer  = file_get_contents($path);
1348:       $file_buffer  = $this->EncodeString($file_buffer, $encoding);
1349:       if (PHP_VERSION < 6) { set_magic_quotes_runtime($magic_quotes); }
1350:       return $file_buffer;
1351:     } catch (Exception $e) {
1352:       $this->SetError($e->getMessage());
1353:       return '';
1354:     }
1355:   }
1356: 
1357:   /**
1358:    * Encodes string to requested format.
1359:    * Returns an empty string on failure.
1360:    * @param string $str The text to encode
1361:    * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
1362:    * @access public
1363:    * @return string
1364:    */
1365:   public function EncodeString ($str, $encoding = 'base64') {
1366:     $encoded = '';
1367:     switch(strtolower($encoding)) {
1368:       case 'base64':
1369:         $encoded = chunk_split(base64_encode($str), 76, $this->LE);
1370:         break;
1371:       case '7bit':
1372:       case '8bit':
1373:         $encoded = $this->FixEOL($str);
1374:         //Make sure it ends with a line break
1375:         if (substr($encoded, -(strlen($this->LE))) != $this->LE)
1376:           $encoded .= $this->LE;
1377:         break;
1378:       case 'binary':
1379:         $encoded = $str;
1380:         break;
1381:       case 'quoted-printable':
1382:         $encoded = $this->EncodeQP($str);
1383:         break;
1384:       default:
1385:         $this->SetError($this->Lang('encoding') . $encoding);
1386:         break;
1387:     }
1388:     return $encoded;
1389:   }
1390: 
1391:   /**
1392:    * Encode a header string to best (shortest) of Q, B, quoted or none.
1393:    * @access public
1394:    * @return string
1395:    */
1396:   public function EncodeHeader($str, $position = 'text') {
1397:     $x = 0;
1398: 
1399:     switch (strtolower($position)) {
1400:       case 'phrase':
1401:         if (!preg_match('/[\200-\377]/', $str)) {
1402:           // Can't use addslashes as we don't know what value has magic_quotes_sybase
1403:           $encoded = addcslashes($str, "\0..\37\177\\\"");
1404:           if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
1405:             return ($encoded);
1406:           } else {
1407:             return ("\"$encoded\"");
1408:           }
1409:         }
1410:         $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
1411:         break;
1412:       case 'comment':
1413:         $x = preg_match_all('/[()"]/', $str, $matches);
1414:         // Fall-through
1415:       case 'text':
1416:       default:
1417:         $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
1418:         break;
1419:     }
1420: 
1421:     if ($x == 0) {
1422:       return ($str);
1423:     }
1424: 
1425:     $maxlen = 75 - 7 - strlen($this->CharSet);
1426:     // Try to select the encoding which should produce the shortest output
1427:     if (strlen($str)/3 < $x) {
1428:       $encoding = 'B';
1429:       if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) {
1430:         // Use a custom function which correctly encodes and wraps long
1431:         // multibyte strings without breaking lines within a character
1432:         $encoded = $this->Base64EncodeWrapMB($str);
1433:       } else {
1434:         $encoded = base64_encode($str);
1435:         $maxlen -= $maxlen % 4;
1436:         $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
1437:       }
1438:     } else {
1439:       $encoding = 'Q';
1440:       $encoded = $this->EncodeQ($str, $position);
1441:       $encoded = $this->WrapText($encoded, $maxlen, true);
1442:       $encoded = str_replace('='.$this->LE, "\n", trim($encoded));
1443:     }
1444: 
1445:     $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);
1446:     $encoded = trim(str_replace("\n", $this->LE, $encoded));
1447: 
1448:     return $encoded;
1449:   }
1450: 
1451:   /**
1452:    * Checks if a string contains multibyte characters.
1453:    * @access public
1454:    * @param string $str multi-byte text to wrap encode
1455:    * @return bool
1456:    */
1457:   public function HasMultiBytes($str) {
1458:     if (function_exists('mb_strlen')) {
1459:       return (strlen($str) > mb_strlen($str, $this->CharSet));
1460:     } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
1461:       return false;
1462:     }
1463:   }
1464: 
1465:   /**
1466:    * Correctly encodes and wraps long multibyte strings for mail headers
1467:    * without breaking lines within a character.
1468:    * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php
1469:    * @access public
1470:    * @param string $str multi-byte text to wrap encode
1471:    * @return string
1472:    */
1473:   public function Base64EncodeWrapMB($str) {
1474:     $start = "=?".$this->CharSet."?B?";
1475:     $end = "?=";
1476:     $encoded = "";
1477: 
1478:     $mb_length = mb_strlen($str, $this->CharSet);
1479:     // Each line must have length <= 75, including $start and $end
1480:     $length = 75 - strlen($start) - strlen($end);
1481:     // Average multi-byte ratio
1482:     $ratio = $mb_length / strlen($str);
1483:     // Base64 has a 4:3 ratio
1484:     $offset = $avgLength = floor($length * $ratio * .75);
1485: 
1486:     for ($i = 0; $i < $mb_length; $i += $offset) {
1487:       $lookBack = 0;
1488: 
1489:       do {
1490:         $offset = $avgLength - $lookBack;
1491:         $chunk = mb_substr($str, $i, $offset, $this->CharSet);
1492:         $chunk = base64_encode($chunk);
1493:         $lookBack++;
1494:       }
1495:       while (strlen($chunk) > $length);
1496: 
1497:       $encoded .= $chunk . $this->LE;
1498:     }
1499: 
1500:     // Chomp the last linefeed
1501:     $encoded = substr($encoded, 0, -strlen($this->LE));
1502:     return $encoded;
1503:   }
1504: 
1505:   /**
1506:   * Encode string to quoted-printable.
1507:   * Only uses standard PHP, slow, but will always work
1508:   * @access public
1509:   * @param string $string the text to encode
1510:   * @param integer $line_max Number of chars allowed on a line before wrapping
1511:   * @return string
1512:   */
1513:   public function EncodeQPphp( $input = '', $line_max = 76, $space_conv = false) {
1514:     $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
1515:     $lines = preg_split('/(?:\r\n|\r|\n)/', $input);
1516:     $eol = "\r\n";
1517:     $escape = '=';
1518:     $output = '';
1519:     while( list(, $line) = each($lines) ) {
1520:       $linlen = strlen($line);
1521:       $newline = '';
1522:       for($i = 0; $i < $linlen; $i++) {
1523:         $c = substr( $line, $i, 1 );
1524:         $dec = ord( $c );
1525:         if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E
1526:           $c = '=2E';
1527:         }
1528:         if ( $dec == 32 ) {
1529:           if ( $i == ( $linlen - 1 ) ) { // convert space at eol only
1530:             $c = '=20';
1531:           } else if ( $space_conv ) {
1532:             $c = '=20';
1533:           }
1534:         } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
1535:           $h2 = floor($dec/16);
1536:           $h1 = floor($dec%16);
1537:           $c = $escape.$hex[$h2].$hex[$h1];
1538:         }
1539:         if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
1540:           $output .= $newline.$escape.$eol; //  soft line break; " =\r\n" is okay
1541:           $newline = '';
1542:           // check if newline first character will be point or not
1543:           if ( $dec == 46 ) {
1544:             $c = '=2E';
1545:           }
1546:         }
1547:         $newline .= $c;
1548:       } // end of for
1549:       $output .= $newline.$eol;
1550:     } // end of while
1551:     return $output;
1552:   }
1553: 
1554:   /**
1555:   * Encode string to RFC2045 (6.7) quoted-printable format
1556:   * Uses a PHP5 stream filter to do the encoding about 64x faster than the old version
1557:   * Also results in same content as you started with after decoding
1558:   * @see EncodeQPphp()
1559:   * @access public
1560:   * @param string $string the text to encode
1561:   * @param integer $line_max Number of chars allowed on a line before wrapping
1562:   * @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function
1563:   * @return string
1564:   * @author Marcus Bointon
1565:   */
1566:   public function EncodeQP($string, $line_max = 76, $space_conv = false) {
1567:     if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3)
1568:       return quoted_printable_encode($string);
1569:     }
1570:     $filters = stream_get_filters();
1571:     if (!in_array('convert.*', $filters)) { //Got convert stream filter?
1572:       return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation
1573:     }
1574:     $fp = fopen('php://temp/', 'r+');
1575:     $string = preg_replace('/\r\n?/', $this->LE, $string); //Normalise line breaks
1576:     $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE);
1577:     $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params);
1578:     fputs($fp, $string);
1579:     rewind($fp);
1580:     $out = stream_get_contents($fp);
1581:     stream_filter_remove($s);
1582:     $out = preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange
1583:     fclose($fp);
1584:     return $out;
1585:   }
1586: 
1587:   /**
1588:    * Encode string to q encoding.
1589:    * @link http://tools.ietf.org/html/rfc2047
1590:    * @param string $str the text to encode
1591:    * @param string $position Where the text is going to be used, see the RFC for what that means
1592:    * @access public
1593:    * @return string
1594:    */
1595:   public function EncodeQ ($str, $position = 'text') {
1596:     // There should not be any EOL in the string
1597:     $encoded = preg_replace('/[\r\n]*/', '', $str);
1598: 
1599:     switch (strtolower($position)) {
1600:       case 'phrase':
1601:         $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
1602:         break;
1603:       case 'comment':
1604:         $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
1605:       case 'text':
1606:       default:
1607:         // Replace every high ascii, control =, ? and _ characters
1608:         //TODO using /e (equivalent to eval()) is probably not a good idea
1609:         $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
1610:               "'='.sprintf('%02X', ord('\\1'))", $encoded);
1611:         break;
1612:     }
1613: 
1614:     // Replace every spaces to _ (more readable than =20)
1615:     $encoded = str_replace(' ', '_', $encoded);
1616: 
1617:     return $encoded;
1618:   }
1619: 
1620:   /**
1621:    * Adds a string or binary attachment (non-filesystem) to the list.
1622:    * This method can be used to attach ascii or binary data,
1623:    * such as a BLOB record from a database.
1624:    * @param string $string String attachment data.
1625:    * @param string $filename Name of the attachment.
1626:    * @param string $encoding File encoding (see $Encoding).
1627:    * @param string $type File extension (MIME) type.
1628:    * @return void
1629:    */
1630:   public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') {
1631:     // Append to $attachment array
1632:     $this->attachment[] = array(
1633:       0 => $string,
1634:       1 => $filename,
1635:       2 => $filename,
1636:       3 => $encoding,
1637:       4 => $type,
1638:       5 => true,  // isStringAttachment
1639:       6 => 'attachment',
1640:       7 => 0
1641:     );
1642:   }
1643: 
1644:   /**
1645:    * Adds an embedded attachment.  This can include images, sounds, and
1646:    * just about any other document.  Make sure to set the $type to an
1647:    * image type.  For JPEG images use "image/jpeg" and for GIF images
1648:    * use "image/gif".
1649:    * @param string $path Path to the attachment.
1650:    * @param string $cid Content ID of the attachment.  Use this to identify
1651:    *        the Id for accessing the image in an HTML form.
1652:    * @param string $name Overrides the attachment name.
1653:    * @param string $encoding File encoding (see $Encoding).
1654:    * @param string $type File extension (MIME) type.
1655:    * @return bool
1656:    */
1657:   public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
1658: 
1659:     if ( !@is_file($path) ) {
1660:       $this->SetError($this->Lang('file_access') . $path);
1661:       return false;
1662:     }
1663: 
1664:     $filename = basename($path);
1665:     if ( $name == '' ) {
1666:       $name = $filename;
1667:     }
1668: 
1669:     // Append to $attachment array
1670:     $this->attachment[] = array(
1671:       0 => $path,
1672:       1 => $filename,
1673:       2 => $name,
1674:       3 => $encoding,
1675:       4 => $type,
1676:       5 => false,  // isStringAttachment
1677:       6 => 'inline',
1678:       7 => $cid
1679:     );
1680: 
1681:     return true;
1682:   }
1683: 
1684:   /**
1685:    * Returns true if an inline attachment is present.
1686:    * @access public
1687:    * @return bool
1688:    */
1689:   public function InlineImageExists() {
1690:     foreach($this->attachment as $attachment) {
1691:       if ($attachment[6] == 'inline') {
1692:         return true;
1693:       }
1694:     }
1695:     return false;
1696:   }
1697: 
1698:   /////////////////////////////////////////////////
1699:   // CLASS METHODS, MESSAGE RESET
1700:   /////////////////////////////////////////////////
1701: 
1702:   /**
1703:    * Clears all recipients assigned in the TO array.  Returns void.
1704:    * @return void
1705:    */
1706:   public function ClearAddresses() {
1707:     foreach($this->to as $to) {
1708:       unset($this->all_recipients[strtolower($to[0])]);
1709:     }
1710:     $this->to = array();
1711:   }
1712: 
1713:   /**
1714:    * Clears all recipients assigned in the CC array.  Returns void.
1715:    * @return void
1716:    */
1717:   public function ClearCCs() {
1718:     foreach($this->cc as $cc) {
1719:       unset($this->all_recipients[strtolower($cc[0])]);
1720:     }
1721:     $this->cc = array();
1722:   }
1723: 
1724:   /**
1725:    * Clears all recipients assigned in the BCC array.  Returns void.
1726:    * @return void
1727:    */
1728:   public function ClearBCCs() {
1729:     foreach($this->bcc as $bcc) {
1730:       unset($this->all_recipients[strtolower($bcc[0])]);
1731:     }
1732:     $this->bcc = array();
1733:   }
1734: 
1735:   /**
1736:    * Clears all recipients assigned in the ReplyTo array.  Returns void.
1737:    * @return void
1738:    */
1739:   public function ClearReplyTos() {
1740:     $this->ReplyTo = array();
1741:   }
1742: 
1743:   /**
1744:    * Clears all recipients assigned in the TO, CC and BCC
1745:    * array.  Returns void.
1746:    * @return void
1747:    */
1748:   public function ClearAllRecipients() {
1749:     $this->to = array();
1750:     $this->cc = array();
1751:     $this->bcc = array();
1752:     $this->all_recipients = array();
1753:   }
1754: 
1755:   /**
1756:    * Clears all previously set filesystem, string, and binary
1757:    * attachments.  Returns void.
1758:    * @return void
1759:    */
1760:   public function ClearAttachments() {
1761:     $this->attachment = array();
1762:   }
1763: 
1764:   /**
1765:    * Clears all custom headers.  Returns void.
1766:    * @return void
1767:    */
1768:   public function ClearCustomHeaders() {
1769:     $this->CustomHeader = array();
1770:   }
1771: 
1772:   /////////////////////////////////////////////////
1773:   // CLASS METHODS, MISCELLANEOUS
1774:   /////////////////////////////////////////////////
1775: 
1776:   /**
1777:    * Adds the error message to the error container.
1778:    * @access protected
1779:    * @return void
1780:    */
1781:   protected function SetError($msg) {
1782:     $this->error_count++;
1783:     if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
1784:       $lasterror = $this->smtp->getError();
1785:       if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) {
1786:         $msg .= '<p>' . $this->Lang('smtp_error') . $lasterror['smtp_msg'] . "</p>\n";
1787:       }
1788:     }
1789:     $this->ErrorInfo = $msg;
1790:   }
1791: 
1792:   /**
1793:    * Returns the proper RFC 822 formatted date.
1794:    * @access public
1795:    * @return string
1796:    * @static
1797:    */
1798:   public static function RFCDate() {
1799:     $tz = date('Z');
1800:     $tzs = ($tz < 0) ? '-' : '+';
1801:     $tz = abs($tz);
1802:     $tz = (int)($tz/3600)*100 + ($tz%3600)/60;
1803:     $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz);
1804: 
1805:     return $result;
1806:   }
1807: 
1808:   /**
1809:    * Returns the server hostname or 'localhost.localdomain' if unknown.
1810:    * @access private
1811:    * @return string
1812:    */
1813:   private function ServerHostname() {
1814:     if (!empty($this->Hostname)) {
1815:       $result = $this->Hostname;
1816:     } elseif (isset($_SERVER['SERVER_NAME'])) {
1817:       $result = $_SERVER['SERVER_NAME'];
1818:     } else {
1819:       $result = 'localhost.localdomain';
1820:     }
1821: 
1822:     return $result;
1823:   }
1824: 
1825:   /**
1826:    * Returns a message in the appropriate language.
1827:    * @access private
1828:    * @return string
1829:    */
1830:   private function Lang($key) {
1831:     if(count($this->language) < 1) {
1832:       $this->SetLanguage('en'); // set the default language
1833:     }
1834: 
1835:     if(isset($this->language[$key])) {
1836:       return $this->language[$key];
1837:     } else {
1838:       return 'Language string failed to load: ' . $key;
1839:     }
1840:   }
1841: 
1842:   /**
1843:    * Returns true if an error occurred.
1844:    * @access public
1845:    * @return bool
1846:    */
1847:   public function IsError() {
1848:     return ($this->error_count > 0);
1849:   }
1850: 
1851:   /**
1852:    * Changes every end of line from CR or LF to CRLF.
1853:    * @access private
1854:    * @return string
1855:    */
1856:   private function FixEOL($str) {
1857:     $str = str_replace("\r\n", "\n", $str);
1858:     $str = str_replace("\r", "\n", $str);
1859:     $str = str_replace("\n", $this->LE, $str);
1860:     return $str;
1861:   }
1862: 
1863:   /**
1864:    * Adds a custom header.
1865:    * @access public
1866:    * @return void
1867:    */
1868:   public function AddCustomHeader($custom_header) {
1869:     $this->CustomHeader[] = explode(':', $custom_header, 2);
1870:   }
1871: 
1872:   /**
1873:    * Evaluates the message and returns modifications for inline images and backgrounds
1874:    * @access public
1875:    * @return $message
1876:    */
1877:   public function MsgHTML($message, $basedir = '') {
1878:     preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images);
1879:     if(isset($images[2])) {
1880:       foreach($images[2] as $i => $url) {
1881:         // do not change urls for absolute images (thanks to corvuscorax)
1882:         if (!preg_match('#^[A-z]+://#',$url)) {
1883:           $filename = basename($url);
1884:           $directory = dirname($url);
1885:           ($directory == '.')?$directory='':'';
1886:           $cid = 'cid:' . md5($filename);
1887:           $ext = pathinfo($filename, PATHINFO_EXTENSION);
1888:           $mimeType  = self::_mime_types($ext);
1889:           if ( strlen($basedir) > 1 && substr($basedir,-1) != '/') { $basedir .= '/'; }
1890:           if ( strlen($directory) > 1 && substr($directory,-1) != '/') { $directory .= '/'; }
1891:           if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64',$mimeType) ) {
1892:             $message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message);
1893:           }
1894:         }
1895:       }
1896:     }
1897:     $this->IsHTML(true);
1898:     $this->Body = $message;
1899:     $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s','',$message)));
1900:     if (!empty($textMsg) && empty($this->AltBody)) {
1901:       $this->AltBody = html_entity_decode($textMsg);
1902:     }
1903:     if (empty($this->AltBody)) {
1904:       $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n";
1905:     }
1906:   }
1907: 
1908:   /**
1909:    * Gets the MIME type of the embedded or inline image
1910:    * @param string File extension
1911:    * @access public
1912:    * @return string MIME type of ext
1913:    * @static
1914:    */
1915:   public static function _mime_types($ext = '') {
1916:     $mimes = array(
1917:       'hqx'   =>  'application/mac-binhex40',
1918:       'cpt'   =>  'application/mac-compactpro',
1919:       'doc'   =>  'application/msword',
1920:       'bin'   =>  'application/macbinary',
1921:       'dms'   =>  'application/octet-stream',
1922:       'lha'   =>  'application/octet-stream',
1923:       'lzh'   =>  'application/octet-stream',
1924:       'exe'   =>  'application/octet-stream',
1925:       'class' =>  'application/octet-stream',
1926:       'psd'   =>  'application/octet-stream',
1927:       'so'    =>  'application/octet-stream',
1928:       'sea'   =>  'application/octet-stream',
1929:       'dll'   =>  'application/octet-stream',
1930:       'oda'   =>  'application/oda',
1931:       'pdf'   =>  'application/pdf',
1932:       'ai'    =>  'application/postscript',
1933:       'eps'   =>  'application/postscript',
1934:       'ps'    =>  'application/postscript',
1935:       'smi'   =>  'application/smil',
1936:       'smil'  =>  'application/smil',
1937:       'mif'   =>  'application/vnd.mif',
1938:       'xls'   =>  'application/vnd.ms-excel',
1939:       'ppt'   =>  'application/vnd.ms-powerpoint',
1940:       'wbxml' =>  'application/vnd.wap.wbxml',
1941:       'wmlc'  =>  'application/vnd.wap.wmlc',
1942:       'dcr'   =>  'application/x-director',
1943:       'dir'   =>  'application/x-director',
1944:       'dxr'   =>  'application/x-director',
1945:       'dvi'   =>  'application/x-dvi',
1946:       'gtar'  =>  'application/x-gtar',
1947:       'php'   =>  'application/x-httpd-php',
1948:       'php4'  =>  'application/x-httpd-php',
1949:       'php3'  =>  'application/x-httpd-php',
1950:       'phtml' =>  'application/x-httpd-php',
1951:       'phps'  =>  'application/x-httpd-php-source',
1952:       'js'    =>  'application/x-javascript',
1953:       'swf'   =>  'application/x-shockwave-flash',
1954:       'sit'   =>  'application/x-stuffit',
1955:       'tar'   =>  'application/x-tar',
1956:       'tgz'   =>  'application/x-tar',
1957:       'xhtml' =>  'application/xhtml+xml',
1958:       'xht'   =>  'application/xhtml+xml',
1959:       'zip'   =>  'application/zip',
1960:       'mid'   =>  'audio/midi',
1961:       'midi'  =>  'audio/midi',
1962:       'mpga'  =>  'audio/mpeg',
1963:       'mp2'   =>  'audio/mpeg',
1964:       'mp3'   =>  'audio/mpeg',
1965:       'aif'   =>  'audio/x-aiff',
1966:       'aiff'  =>  'audio/x-aiff',
1967:       'aifc'  =>  'audio/x-aiff',
1968:       'ram'   =>  'audio/x-pn-realaudio',
1969:       'rm'    =>  'audio/x-pn-realaudio',
1970:       'rpm'   =>  'audio/x-pn-realaudio-plugin',
1971:       'ra'    =>  'audio/x-realaudio',
1972:       'rv'    =>  'video/vnd.rn-realvideo',
1973:       'wav'   =>  'audio/x-wav',
1974:       'bmp'   =>  'image/bmp',
1975:       'gif'   =>  'image/gif',
1976:       'jpeg'  =>  'image/jpeg',
1977:       'jpg'   =>  'image/jpeg',
1978:       'jpe'   =>  'image/jpeg',
1979:       'png'   =>  'image/png',
1980:       'tiff'  =>  'image/tiff',
1981:       'tif'   =>  'image/tiff',
1982:       'css'   =>  'text/css',
1983:       'html'  =>  'text/html',
1984:       'htm'   =>  'text/html',
1985:       'shtml' =>  'text/html',
1986:       'txt'   =>  'text/plain',
1987:       'text'  =>  'text/plain',
1988:       'log'   =>  'text/plain',
1989:       'rtx'   =>  'text/richtext',
1990:       'rtf'   =>  'text/rtf',
1991:       'xml'   =>  'text/xml',
1992:       'xsl'   =>  'text/xml',
1993:       'mpeg'  =>  'video/mpeg',
1994:       'mpg'   =>  'video/mpeg',
1995:       'mpe'   =>  'video/mpeg',
1996:       'qt'    =>  'video/quicktime',
1997:       'mov'   =>  'video/quicktime',
1998:       'avi'   =>  'video/x-msvideo',
1999:       'movie' =>  'video/x-sgi-movie',
2000:       'doc'   =>  'application/msword',
2001:       'word'  =>  'application/msword',
2002:       'xl'    =>  'application/excel',
2003:       'eml'   =>  'message/rfc822'
2004:     );
2005:     return (!isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];
2006:   }
2007: 
2008:   /**
2009:   * Set (or reset) Class Objects (variables)
2010:   *
2011:   * Usage Example:
2012:   * $page->set('X-Priority', '3');
2013:   *
2014:   * @access public
2015:   * @param string $name Parameter Name
2016:   * @param mixed $value Parameter Value
2017:   * NOTE: will not work with arrays, there are no arrays to set/reset
2018:   * @todo Should this not be using __set() magic function?
2019:   */
2020:   public function set($name, $value = '') {
2021:     try {
2022:       if (isset($this->$name) ) {
2023:         $this->$name = $value;
2024:       } else {
2025:         throw new phpmailerException($this->Lang('variable_set') . $name, self::STOP_CRITICAL);
2026:       }
2027:     } catch (Exception $e) {
2028:       $this->SetError($e->getMessage());
2029:       if ($e->getCode() == self::STOP_CRITICAL) {
2030:         return false;
2031:       }
2032:     }
2033:     return true;
2034:   }
2035: 
2036:   /**
2037:    * Strips newlines to prevent header injection.
2038:    * @access public
2039:    * @param string $str String
2040:    * @return string
2041:    */
2042:   public function SecureHeader($str) {
2043:     $str = str_replace("\r", '', $str);
2044:     $str = str_replace("\n", '', $str);
2045:     return trim($str);
2046:   }
2047: 
2048:   /**
2049:    * Set the private key file and password to sign the message.
2050:    *
2051:    * @access public
2052:    * @param string $key_filename Parameter File Name
2053:    * @param string $key_pass Password for private key
2054:    */
2055:   public function Sign($cert_filename, $key_filename, $key_pass) {
2056:     $this->sign_cert_file = $cert_filename;
2057:     $this->sign_key_file = $key_filename;
2058:     $this->sign_key_pass = $key_pass;
2059:   }
2060: }
2061: 
2062: class phpmailerException extends Exception {
2063:   public function errorMessage() {
2064:     $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n";
2065:     return $errorMsg;
2066:   }
2067: }
2068: ?>