(no commit message)
[mailer.git] / 0.2.1 / inc / phpmailer / class.phpmailer.php
1 <?php
2 /*~ class.phpmailer.php
3 .---------------------------------------------------------------------------.
4 |  Software: PHPMailer - PHP email class                                    |
5 |   Version: 2.0.0 rc3                                                      |
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 |    Author: Andy Prevost (project admininistrator)                         |
11 |    Author: Brent R. Matzelle (original founder)                           |
12 | Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved.               |
13 | Copyright (c) 2001-2003, Brent R. Matzelle                                |
14 | ------------------------------------------------------------------------- |
15 |   License: Distributed under the Lesser General Public License (LGPL)     |
16 |            http://www.gnu.org/copyleft/lesser.html                        |
17 | This program is distributed in the hope that it will be useful - WITHOUT  |
18 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
19 | FITNESS FOR A PARTICULAR PURPOSE.                                         |
20 | ------------------------------------------------------------------------- |
21 | We offer a number of paid services (www.codeworxtech.com):                |
22 | - Web Hosting on highly optimized fast and secure servers                 |
23 | - Technology Consulting                                                   |
24 | - Oursourcing (highly qualified programmers and graphic designers)        |
25 '---------------------------------------------------------------------------'
26
27 /**
28  * PHPMailer - PHP email transport class
29  * @package PHPMailer
30  * @author Andy Prevost
31  * @copyright 2004 - 2007 Andy Prevost
32  */
33
34 class PHPMailer {
35
36   /////////////////////////////////////////////////
37   // PROPERTIES, PUBLIC
38   /////////////////////////////////////////////////
39
40   /**
41    * Email priority (1 = High, 3 = Normal, 5 = low).
42    * @var int
43    */
44   var $Priority          = 3;
45
46   /**
47    * Sets the CharSet of the message.
48    * @var string
49    */
50   var $CharSet           = 'iso-8859-1';
51
52   /**
53    * Sets the Content-type of the message.
54    * @var string
55    */
56   var $ContentType        = 'text/plain';
57
58   /**
59    * Sets the Encoding of the message. Options for this are "8bit",
60    * "7bit", "binary", "base64", and "quoted-printable".
61    * @var string
62    */
63   var $Encoding          = '8bit';
64
65   /**
66    * Holds the most recent mailer error message.
67    * @var string
68    */
69   var $ErrorInfo         = '';
70
71   /**
72    * Sets the From email address for the message.
73    * @var string
74    */
75   var $From              = 'root@localhost';
76
77   /**
78    * Sets the From name of the message.
79    * @var string
80    */
81   var $FromName          = 'Root User';
82
83   /**
84    * Sets the Sender email (Return-Path) of the message.  If not empty,
85    * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
86    * @var string
87    */
88   var $Sender            = '';
89
90   /**
91    * Sets the Subject of the message.
92    * @var string
93    */
94   var $Subject           = '';
95
96   /**
97    * Sets the Body of the message.  This can be either an HTML or text body.
98    * If HTML then run IsHTML(true).
99    * @var string
100    */
101   var $Body              = '';
102
103   /**
104    * Sets the text-only body of the message.  This automatically sets the
105    * email to multipart/alternative.  This body can be read by mail
106    * clients that do not have HTML email capability such as mutt. Clients
107    * that can read HTML will view the normal Body.
108    * @var string
109    */
110   var $AltBody           = '';
111
112   /**
113    * Sets word wrapping on the body of the message to a given number of
114    * characters.
115    * @var int
116    */
117   var $WordWrap          = 0;
118
119   /**
120    * Method to send mail: ("mail", "sendmail", or "smtp").
121    * @var string
122    */
123   var $Mailer            = 'mail';
124
125   /**
126    * Sets the path of the sendmail program.
127    * @var string
128    */
129   var $Sendmail          = '/usr/sbin/sendmail';
130
131   /**
132    * Path to PHPMailer plugins.  This is now only useful if the SMTP class
133    * is in a different directory than the PHP include path.
134    * @var string
135    */
136   var $PluginDir         = '';
137
138   /**
139    * Holds PHPMailer version.
140    * @var string
141    */
142   var $Version           = "2.0.0 rc3";
143
144   /**
145    * Sets the email address that a reading confirmation will be sent.
146    * @var string
147    */
148   var $ConfirmReadingTo  = '';
149
150   /**
151    * Sets the hostname to use in Message-Id and Received headers
152    * and as default HELO string. If empty, the value returned
153    * by SERVER_NAME is used or 'localhost.localdomain'.
154    * @var string
155    */
156   var $Hostname          = '';
157
158   /////////////////////////////////////////////////
159   // PROPERTIES FOR SMTP
160   /////////////////////////////////////////////////
161
162   /**
163    * Sets the SMTP hosts.  All hosts must be separated by a
164    * semicolon.  You can also specify a different port
165    * for each host by using this format: [hostname:port]
166    * (e.g. "smtp1.example.com:25;smtp2.example.com").
167    * Hosts will be tried in order.
168    * @var string
169    */
170   var $Host        = 'localhost';
171
172   /**
173    * Sets the default SMTP server port.
174    * @var int
175    */
176   var $Port        = 25;
177
178   /**
179    * Sets the SMTP HELO of the message (Default is $Hostname).
180    * @var string
181    */
182   var $Helo        = '';
183
184   /**
185    * Sets connection prefix.
186    * Options are "", "ssl" or "tls"
187    * @var string
188    */
189   var $SMTPSecure = "";
190
191   /**
192    * Sets SMTP authentication. Utilizes the Username and Password variables.
193    * @var bool
194    */
195   var $SMTPAuth     = false;
196
197   /**
198    * Sets SMTP username.
199    * @var string
200    */
201   var $Username     = '';
202
203   /**
204    * Sets SMTP password.
205    * @var string
206    */
207   var $Password     = '';
208
209   /**
210    * Sets the SMTP server timeout in seconds. This function will not
211    * work with the win32 version.
212    * @var int
213    */
214   var $Timeout      = 10;
215
216   /**
217    * Sets SMTP class debugging on or off.
218    * @var bool
219    */
220   var $SMTPDebug    = false;
221
222   /**
223    * Prevents the SMTP connection from being closed after each mail
224    * sending.  If this is set to true then to close the connection
225    * requires an explicit call to SmtpClose().
226    * @var bool
227    */
228   var $SMTPKeepAlive = false;
229
230   /**
231    * Provides the ability to have the TO field process individual
232    * emails, instead of sending to entire TO addresses
233    * @var bool
234    */
235   var $SingleTo = false;
236
237   /////////////////////////////////////////////////
238   // PROPERTIES, PRIVATE
239   /////////////////////////////////////////////////
240
241   var $smtp            = NULL;
242   var $to              = array();
243   var $cc              = array();
244   var $bcc             = array();
245   var $ReplyTo         = array();
246   var $attachment      = array();
247   var $CustomHeader    = array();
248   var $message_type    = '';
249   var $boundary        = array();
250   var $language        = array();
251   var $error_count     = 0;
252   var $LE              = "\n";
253
254   /////////////////////////////////////////////////
255   // METHODS, VARIABLES
256   /////////////////////////////////////////////////
257
258   /**
259    * Sets message type to HTML.
260    * @param bool $bool
261    * @return void
262    */
263   function IsHTML($bool) {
264     if($bool == true) {
265       $this->ContentType = 'text/html';
266     } else {
267       $this->ContentType = 'text/plain';
268     }
269   }
270
271   /**
272    * Sets Mailer to send message using SMTP.
273    * @return void
274    */
275   function IsSMTP() {
276     $this->Mailer = 'smtp';
277   }
278
279   /**
280    * Sets Mailer to send message using PHP mail() function.
281    * @return void
282    */
283   function IsMail() {
284     $this->Mailer = 'mail';
285   }
286
287   /**
288    * Sets Mailer to send message using the $Sendmail program.
289    * @return void
290    */
291   function IsSendmail() {
292     $this->Mailer = 'sendmail';
293   }
294
295   /**
296    * Sets Mailer to send message using the qmail MTA.
297    * @return void
298    */
299   function IsQmail() {
300     $this->Sendmail = '/var/qmail/bin/sendmail';
301     $this->Mailer = 'sendmail';
302   }
303
304   /////////////////////////////////////////////////
305   // METHODS, RECIPIENTS
306   /////////////////////////////////////////////////
307
308   /**
309    * Adds a "To" address.
310    * @param string $address
311    * @param string $name
312    * @return void
313    */
314   function AddAddress($address, $name = '') {
315     $cur = count($this->to);
316     $this->to[$cur][0] = trim($address);
317     $this->to[$cur][1] = $name;
318   }
319
320   /**
321    * Adds a "Cc" address. Note: this function works
322    * with the SMTP mailer on win32, not with the "mail"
323    * mailer.
324    * @param string $address
325    * @param string $name
326    * @return void
327    */
328   function AddCC($address, $name = '') {
329     $cur = count($this->cc);
330     $this->cc[$cur][0] = trim($address);
331     $this->cc[$cur][1] = $name;
332   }
333
334   /**
335    * Adds a "Bcc" address. Note: this function works
336    * with the SMTP mailer on win32, not with the "mail"
337    * mailer.
338    * @param string $address
339    * @param string $name
340    * @return void
341    */
342   function AddBCC($address, $name = '') {
343     $cur = count($this->bcc);
344     $this->bcc[$cur][0] = trim($address);
345     $this->bcc[$cur][1] = $name;
346   }
347
348   /**
349    * Adds a "Reply-To" address.
350    * @param string $address
351    * @param string $name
352    * @return void
353    */
354   function AddReplyTo($address, $name = '') {
355     $cur = count($this->ReplyTo);
356     $this->ReplyTo[$cur][0] = trim($address);
357     $this->ReplyTo[$cur][1] = $name;
358   }
359
360   /////////////////////////////////////////////////
361   // METHODS, MAIL SENDING
362   /////////////////////////////////////////////////
363
364   /**
365    * Creates message and assigns Mailer. If the message is
366    * not sent successfully then it returns false.  Use the ErrorInfo
367    * variable to view description of the error.
368    * @return bool
369    */
370   function Send() {
371     $header = '';
372     $body = '';
373     $result = true;
374
375     if((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
376       $this->SetError($this->Lang('provide_address'));
377       return false;
378     }
379
380     /* Set whether the message is multipart/alternative */
381     if(!empty($this->AltBody)) {
382       $this->ContentType = 'multipart/alternative';
383     }
384
385     $this->error_count = 0; // reset errors
386     $this->SetMessageType();
387     $header .= $this->CreateHeader();
388     $body = $this->CreateBody();
389
390     if($body == '') {
391       return false;
392     }
393
394     /* Choose the mailer */
395     switch($this->Mailer) {
396       case 'sendmail':
397         $result = $this->SendmailSend($header, $body);
398         break;
399       case 'smtp':
400         $result = $this->SmtpSend($header, $body);
401         break;
402       case 'mail':
403         $result = $this->MailSend($header, $body);
404         break;
405       default:
406         $result = $this->MailSend($header, $body);
407         break;
408         //$this->SetError($this->Mailer . $this->Lang('mailer_not_supported'));
409         //$result = false;
410         //break;
411     }
412
413     return $result;
414   }
415
416   /**
417    * Sends mail using the $Sendmail program.
418    * @access private
419    * @return bool
420    */
421   function SendmailSend($header, $body) {
422     if ($this->Sender != '') {
423       $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
424     } else {
425       $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
426     }
427
428     if(!@$mail = popen($sendmail, 'w')) {
429       $this->SetError($this->Lang('execute') . $this->Sendmail);
430       return false;
431     }
432
433     fputs($mail, $header);
434     fputs($mail, $body);
435
436     $result = pclose($mail) >> 8 & 0xFF;
437     if($result != 0) {
438       $this->SetError($this->Lang('execute') . $this->Sendmail);
439       return false;
440     }
441
442     return true;
443   }
444
445   /**
446    * Sends mail using the PHP mail() function.
447    * @access private
448    * @return bool
449    */
450   function MailSend($header, $body) {
451
452     $to = '';
453     for($i = 0; $i < count($this->to); $i++) {
454       if($i != 0) { $to .= ', '; }
455       $to .= $this->AddrFormat($this->to[$i]);
456     }
457
458     $toArr = split(',', $to);
459
460     if ($this->Sender != '' && strlen(ini_get('safe_mode'))< 1) {
461       $old_from = ini_get('sendmail_from');
462       ini_set('sendmail_from', $this->Sender);
463       $params = sprintf("-oi -f %s", $this->Sender);
464       if ($this->SingleTo === true && count($toArr) > 1) {
465         foreach ($toArr as $key => $val) {
466           $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
467         }
468       } else {
469         $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
470       }
471     } else {
472       if ($this->SingleTo === true && count($toArr) > 1) {
473         foreach ($toArr as $key => $val) {
474           $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
475         }
476       } else {
477         $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header);
478       }
479     }
480
481     if (isset($old_from)) {
482       ini_set('sendmail_from', $old_from);
483     }
484
485     if(!$rt) {
486       $this->SetError($this->Lang('instantiate'));
487       return false;
488     }
489
490     return true;
491   }
492
493   /**
494    * Sends mail via SMTP using PhpSMTP (Author:
495    * Chris Ryan).  Returns bool.  Returns false if there is a
496    * bad MAIL FROM, RCPT, or DATA input.
497    * @access private
498    * @return bool
499    */
500   function SmtpSend($header, $body) {
501     include_once($this->PluginDir . 'class.smtp.php');
502     $error = '';
503     $bad_rcpt = array();
504
505     if(!$this->SmtpConnect()) {
506       return false;
507     }
508
509     $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
510     if(!$this->smtp->Mail($smtp_from)) {
511       $error = $this->Lang('from_failed') . $smtp_from;
512       $this->SetError($error);
513       $this->smtp->Reset();
514       return false;
515     }
516
517     /* Attempt to send attach all recipients */
518     for($i = 0; $i < count($this->to); $i++) {
519       if(!$this->smtp->Recipient($this->to[$i][0])) {
520         $bad_rcpt[] = $this->to[$i][0];
521       }
522     }
523     for($i = 0; $i < count($this->cc); $i++) {
524       if(!$this->smtp->Recipient($this->cc[$i][0])) {
525         $bad_rcpt[] = $this->cc[$i][0];
526       }
527     }
528     for($i = 0; $i < count($this->bcc); $i++) {
529       if(!$this->smtp->Recipient($this->bcc[$i][0])) {
530         $bad_rcpt[] = $this->bcc[$i][0];
531       }
532     }
533
534     if(count($bad_rcpt) > 0) { // Create error message
535       for($i = 0; $i < count($bad_rcpt); $i++) {
536         if($i != 0) {
537           $error .= ', ';
538         }
539         $error .= $bad_rcpt[$i];
540       }
541       $error = $this->Lang('recipients_failed') . $error;
542       $this->SetError($error);
543       $this->smtp->Reset();
544       return false;
545     }
546
547     if(!$this->smtp->Data($header . $body)) {
548       $this->SetError($this->Lang('data_not_accepted'));
549       $this->smtp->Reset();
550       return false;
551     }
552     if($this->SMTPKeepAlive == true) {
553       $this->smtp->Reset();
554     } else {
555       $this->SmtpClose();
556     }
557
558     return true;
559   }
560
561   /**
562    * Initiates a connection to an SMTP server.  Returns false if the
563    * operation failed.
564    * @access private
565    * @return bool
566    */
567   function SmtpConnect() {
568     if($this->smtp == NULL) {
569       $this->smtp = new SMTP();
570     }
571
572     $this->smtp->do_debug = $this->SMTPDebug;
573     $hosts = explode(';', $this->Host);
574     $index = 0;
575     $connection = ($this->smtp->Connected());
576
577     /* Retry while there is no connection */
578     while($index < count($hosts) && $connection == false) {
579       $hostinfo = array();
580       if(eregi('^(.+):([0-9]+)$', $hosts[$index], $hostinfo)) {
581         $host = $hostinfo[1];
582         $port = $hostinfo[2];
583       } else {
584         $host = $hosts[$index];
585         $port = $this->Port;
586       }
587
588       if($this->smtp->Connect(((!empty($this->SMTPSecure))?$this->SMTPSecure.'://':'').$host, $port, $this->Timeout)) {
589         if ($this->Helo != '') {
590           $this->smtp->Hello($this->Helo);
591         } else {
592           $this->smtp->Hello($this->ServerHostname());
593         }
594
595         $connection = true;
596         if($this->SMTPAuth) {
597           if(!$this->smtp->Authenticate($this->Username, $this->Password)) {
598             $this->SetError($this->Lang('authenticate'));
599             $this->smtp->Reset();
600             $connection = false;
601           }
602         }
603       }
604       $index++;
605     }
606     if(!$connection) {
607       $this->SetError($this->Lang('connect_host'));
608     }
609
610     return $connection;
611   }
612
613   /**
614    * Closes the active SMTP session if one exists.
615    * @return void
616    */
617   function SmtpClose() {
618     if($this->smtp != NULL) {
619       if($this->smtp->Connected()) {
620         $this->smtp->Quit();
621         $this->smtp->Close();
622       }
623     }
624   }
625
626   /**
627    * Sets the language for all class error messages.  Returns false
628    * if it cannot load the language file.  The default language type
629    * is English.
630    * @param string $lang_type Type of language (e.g. Portuguese: "br")
631    * @param string $lang_path Path to the language file directory
632    * @access public
633    * @return bool
634    */
635   function SetLanguage($lang_type, $lang_path = 'language/') {
636     if(file_exists($lang_path.'phpmailer.lang-'.$lang_type.'.php')) {
637       include($lang_path.'phpmailer.lang-'.$lang_type.'.php');
638     } elseif (file_exists($lang_path.'phpmailer.lang-en.php')) {
639       include($lang_path.'phpmailer.lang-en.php');
640     } else {
641       $this->SetError('Could not load language file');
642       return false;
643     }
644     $this->language = $PHPMAILER_LANG;
645
646     return true;
647   }
648
649   /////////////////////////////////////////////////
650   // METHODS, MESSAGE CREATION
651   /////////////////////////////////////////////////
652
653   /**
654    * Creates recipient headers.
655    * @access private
656    * @return string
657    */
658   function AddrAppend($type, $addr) {
659     $addr_str = $type . ': ';
660     $addr_str .= $this->AddrFormat($addr[0]);
661     if(count($addr) > 1) {
662       for($i = 1; $i < count($addr); $i++) {
663         $addr_str .= ', ' . $this->AddrFormat($addr[$i]);
664       }
665     }
666     $addr_str .= $this->LE;
667
668     return $addr_str;
669   }
670
671   /**
672    * Formats an address correctly.
673    * @access private
674    * @return string
675    */
676   function AddrFormat($addr) {
677     if(empty($addr[1])) {
678       $formatted = $this->SecureHeader($addr[0]);
679     } else {
680       $formatted = $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
681     }
682
683     return $formatted;
684   }
685
686   /**
687    * Wraps message for use with mailers that do not
688    * automatically perform wrapping and for quoted-printable.
689    * Original written by philippe.
690    * @access private
691    * @return string
692    */
693   function WrapText($message, $length, $qp_mode = false) {
694     $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
695
696     $message = $this->FixEOL($message);
697     if (substr($message, -1) == $this->LE) {
698       $message = substr($message, 0, -1);
699     }
700
701     $line = explode($this->LE, $message);
702     $message = '';
703     for ($i=0 ;$i < count($line); $i++) {
704       $line_part = explode(' ', $line[$i]);
705       $buf = '';
706       for ($e = 0; $e<count($line_part); $e++) {
707         $word = $line_part[$e];
708         if ($qp_mode and (strlen($word) > $length)) {
709           $space_left = $length - strlen($buf) - 1;
710           if ($e != 0) {
711             if ($space_left > 20) {
712               $len = $space_left;
713               if (substr($word, $len - 1, 1) == '=') {
714                 $len--;
715               } elseif (substr($word, $len - 2, 1) == '=') {
716                 $len -= 2;
717               }
718               $part = substr($word, 0, $len);
719               $word = substr($word, $len);
720               $buf .= ' ' . $part;
721               $message .= $buf . sprintf("=%s", $this->LE);
722             } else {
723               $message .= $buf . $soft_break;
724             }
725             $buf = '';
726           }
727           while (strlen($word) > 0) {
728             $len = $length;
729             if (substr($word, $len - 1, 1) == '=') {
730               $len--;
731             } elseif (substr($word, $len - 2, 1) == '=') {
732               $len -= 2;
733             }
734             $part = substr($word, 0, $len);
735             $word = substr($word, $len);
736
737             if (strlen($word) > 0) {
738               $message .= $part . sprintf("=%s", $this->LE);
739             } else {
740               $buf = $part;
741             }
742           }
743         } else {
744           $buf_o = $buf;
745           $buf .= ($e == 0) ? $word : (' ' . $word);
746
747           if (strlen($buf) > $length and $buf_o != '') {
748             $message .= $buf_o . $soft_break;
749             $buf = $word;
750           }
751         }
752       }
753       $message .= $buf . $this->LE;
754     }
755
756     return $message;
757   }
758
759   /**
760    * Set the body wrapping.
761    * @access private
762    * @return void
763    */
764   function SetWordWrap() {
765     if($this->WordWrap < 1) {
766       return;
767     }
768
769     switch($this->message_type) {
770       case 'alt':
771         /* fall through */
772       case 'alt_attachments':
773         $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
774         break;
775       default:
776         $this->Body = $this->WrapText($this->Body, $this->WordWrap);
777         break;
778     }
779   }
780
781   /**
782    * Assembles message header.
783    * @access private
784    * @return string
785    */
786   function CreateHeader() {
787     $result = '';
788
789     /* Set the boundaries */
790     $uniq_id = md5(uniqid(time()));
791     $this->boundary[1] = 'b1_' . $uniq_id;
792     $this->boundary[2] = 'b2_' . $uniq_id;
793
794     $result .= $this->HeaderLine('Date', $this->RFCDate());
795     if($this->Sender == '') {
796       $result .= $this->HeaderLine('Return-Path', trim($this->From));
797     } else {
798       $result .= $this->HeaderLine('Return-Path', trim($this->Sender));
799     }
800
801     /* To be created automatically by mail() */
802     if($this->Mailer != 'mail') {
803       if(count($this->to) > 0) {
804         $result .= $this->AddrAppend('To', $this->to);
805       } elseif (count($this->cc) == 0) {
806         $result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
807       }
808       if(count($this->cc) > 0) {
809         $result .= $this->AddrAppend('Cc', $this->cc);
810       }
811     }
812
813     $from = array();
814     $from[0][0] = trim($this->From);
815     $from[0][1] = $this->FromName;
816     $result .= $this->AddrAppend('From', $from);
817
818     /* sendmail and mail() extract Cc from the header before sending */
819     if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->cc) > 0)) {
820       $result .= $this->AddrAppend('Cc', $this->cc);
821     }
822
823     /* sendmail and mail() extract Bcc from the header before sending */
824     if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
825       $result .= $this->AddrAppend('Bcc', $this->bcc);
826     }
827
828     if(count($this->ReplyTo) > 0) {
829       $result .= $this->AddrAppend('Reply-To', $this->ReplyTo);
830     }
831
832     /* mail() sets the subject itself */
833     if($this->Mailer != 'mail') {
834       $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
835     }
836
837     $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
838     $result .= $this->HeaderLine('X-Priority', $this->Priority);
839     $result .= $this->HeaderLine('X-Mailer', 'PHPMailer (phpmailer.sourceforge.net) [version ' . $this->Version . ']');
840
841     if($this->ConfirmReadingTo != '') {
842       $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
843     }
844
845     // Add custom headers
846     for($index = 0; $index < count($this->CustomHeader); $index++) {
847       $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1])));
848     }
849     $result .= $this->HeaderLine('MIME-Version', '1.0');
850
851     switch($this->message_type) {
852       case 'plain':
853         $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
854         $result .= sprintf("Content-Type: %s; charset=\"%s\"", $this->ContentType, $this->CharSet);
855         break;
856       case 'attachments':
857         /* fall through */
858       case 'alt_attachments':
859         if($this->InlineImageExists()){
860           $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE);
861         } else {
862           $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');
863           $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
864         }
865         break;
866       case 'alt':
867         $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
868         $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
869         break;
870     }
871
872     if($this->Mailer != 'mail') {
873       $result .= $this->LE.$this->LE;
874     }
875
876     return $result;
877   }
878
879   /**
880    * Assembles the message body.  Returns an empty string on failure.
881    * @access private
882    * @return string
883    */
884   function CreateBody() {
885     $result = '';
886
887     $this->SetWordWrap();
888
889     switch($this->message_type) {
890       case 'alt':
891         $result .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
892         $result .= $this->EncodeString($this->AltBody, $this->Encoding);
893         $result .= $this->LE.$this->LE;
894         $result .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
895         $result .= $this->EncodeString($this->Body, $this->Encoding);
896         $result .= $this->LE.$this->LE;
897         $result .= $this->EndBoundary($this->boundary[1]);
898         break;
899       case 'plain':
900         $result .= $this->EncodeString($this->Body, $this->Encoding);
901         break;
902       case 'attachments':
903         $result .= $this->GetBoundary($this->boundary[1], '', '', '');
904         $result .= $this->EncodeString($this->Body, $this->Encoding);
905         $result .= $this->LE;
906         $result .= $this->AttachAll();
907         break;
908       case 'alt_attachments':
909         $result .= sprintf("--%s%s", $this->boundary[1], $this->LE);
910         $result .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE);
911         $result .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body
912         $result .= $this->EncodeString($this->AltBody, $this->Encoding);
913         $result .= $this->LE.$this->LE;
914         $result .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body
915         $result .= $this->EncodeString($this->Body, $this->Encoding);
916         $result .= $this->LE.$this->LE;
917         $result .= $this->EndBoundary($this->boundary[2]);
918         $result .= $this->AttachAll();
919         break;
920     }
921     if($this->IsError()) {
922       $result = '';
923     }
924
925     return $result;
926   }
927
928   /**
929    * Returns the start of a message boundary.
930    * @access private
931    */
932   function GetBoundary($boundary, $charSet, $contentType, $encoding) {
933     $result = '';
934     if($charSet == '') {
935       $charSet = $this->CharSet;
936     }
937     if($contentType == '') {
938       $contentType = $this->ContentType;
939     }
940     if($encoding == '') {
941       $encoding = $this->Encoding;
942     }
943     $result .= $this->TextLine('--' . $boundary);
944     $result .= sprintf("Content-Type: %s; charset = \"%s\"", $contentType, $charSet);
945     $result .= $this->LE;
946     $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding);
947     $result .= $this->LE;
948
949     return $result;
950   }
951
952   /**
953    * Returns the end of a message boundary.
954    * @access private
955    */
956   function EndBoundary($boundary) {
957     return $this->LE . '--' . $boundary . '--' . $this->LE;
958   }
959
960   /**
961    * Sets the message type.
962    * @access private
963    * @return void
964    */
965   function SetMessageType() {
966     if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) {
967       $this->message_type = 'plain';
968     } else {
969       if(count($this->attachment) > 0) {
970         $this->message_type = 'attachments';
971       }
972       if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) {
973         $this->message_type = 'alt';
974       }
975       if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) {
976         $this->message_type = 'alt_attachments';
977       }
978     }
979   }
980
981   /* Returns a formatted header line.
982    * @access private
983    * @return string
984    */
985   function HeaderLine($name, $value) {
986     return $name . ': ' . $value . $this->LE;
987   }
988
989   /**
990    * Returns a formatted mail line.
991    * @access private
992    * @return string
993    */
994   function TextLine($value) {
995     return $value . $this->LE;
996   }
997
998   /////////////////////////////////////////////////
999   // CLASS METHODS, ATTACHMENTS
1000   /////////////////////////////////////////////////
1001
1002   /**
1003    * Adds an attachment from a path on the filesystem.
1004    * Returns false if the file could not be found
1005    * or accessed.
1006    * @param string $path Path to the attachment.
1007    * @param string $name Overrides the attachment name.
1008    * @param string $encoding File encoding (see $Encoding).
1009    * @param string $type File extension (MIME) type.
1010    * @return bool
1011    */
1012   function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
1013     if(!@is_file($path)) {
1014       $this->SetError($this->Lang('file_access') . $path);
1015       return false;
1016     }
1017
1018     $filename = basename($path);
1019     if($name == '') {
1020       $name = $filename;
1021     }
1022
1023     $cur = count($this->attachment);
1024     $this->attachment[$cur][0] = $path;
1025     $this->attachment[$cur][1] = $filename;
1026     $this->attachment[$cur][2] = $name;
1027     $this->attachment[$cur][3] = $encoding;
1028     $this->attachment[$cur][4] = $type;
1029     $this->attachment[$cur][5] = false; // isStringAttachment
1030     $this->attachment[$cur][6] = 'attachment';
1031     $this->attachment[$cur][7] = 0;
1032
1033     return true;
1034   }
1035
1036   /**
1037    * Attaches all fs, string, and binary attachments to the message.
1038    * Returns an empty string on failure.
1039    * @access private
1040    * @return string
1041    */
1042   function AttachAll() {
1043     /* Return text of body */
1044     $mime = array();
1045
1046     /* Add all attachments */
1047     for($i = 0; $i < count($this->attachment); $i++) {
1048       /* Check for string attachment */
1049       $bString = $this->attachment[$i][5];
1050       if ($bString) {
1051         $string = $this->attachment[$i][0];
1052       } else {
1053         $path = $this->attachment[$i][0];
1054       }
1055
1056       $filename    = $this->attachment[$i][1];
1057       $name        = $this->attachment[$i][2];
1058       $encoding    = $this->attachment[$i][3];
1059       $type        = $this->attachment[$i][4];
1060       $disposition = $this->attachment[$i][6];
1061       $cid         = $this->attachment[$i][7];
1062
1063       $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);
1064       $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $name, $this->LE);
1065       $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
1066
1067       if($disposition == 'inline') {
1068         $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
1069       }
1070
1071       $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $name, $this->LE.$this->LE);
1072
1073       /* Encode as string attachment */
1074       if($bString) {
1075         $mime[] = $this->EncodeString($string, $encoding);
1076         if($this->IsError()) {
1077           return '';
1078         }
1079         $mime[] = $this->LE.$this->LE;
1080       } else {
1081         $mime[] = $this->EncodeFile($path, $encoding);
1082         if($this->IsError()) {
1083           return '';
1084         }
1085         $mime[] = $this->LE.$this->LE;
1086       }
1087     }
1088
1089     $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE);
1090
1091     return join('', $mime);
1092   }
1093
1094   /**
1095    * Encodes attachment in requested format.  Returns an
1096    * empty string on failure.
1097    * @access private
1098    * @return string
1099    */
1100   function EncodeFile ($path, $encoding = 'base64') {
1101     if(!@$fd = fopen($path, 'rb')) {
1102       $this->SetError($this->Lang('file_open') . $path);
1103       return '';
1104     }
1105     $magic_quotes = get_magic_quotes_runtime();
1106     set_magic_quotes_runtime(0);
1107     $file_buffer = fread($fd, filesize($path));
1108     $file_buffer = $this->EncodeString($file_buffer, $encoding);
1109     fclose($fd);
1110     set_magic_quotes_runtime($magic_quotes);
1111
1112     return $file_buffer;
1113   }
1114
1115   /**
1116    * Encodes string to requested format. Returns an
1117    * empty string on failure.
1118    * @access private
1119    * @return string
1120    */
1121   function EncodeString ($str, $encoding = 'base64') {
1122     $encoded = '';
1123     switch(strtolower($encoding)) {
1124       case 'base64':
1125         /* chunk_split is found in PHP >= 3.0.6 */
1126         $encoded = chunk_split(base64_encode($str), 76, $this->LE);
1127         break;
1128       case '7bit':
1129       case '8bit':
1130         $encoded = $this->FixEOL($str);
1131         if (substr($encoded, -(strlen($this->LE))) != $this->LE)
1132           $encoded .= $this->LE;
1133         break;
1134       case 'binary':
1135         $encoded = $str;
1136         break;
1137       case 'quoted-printable':
1138         $encoded = $this->EncodeQP($str);
1139         break;
1140       default:
1141         $this->SetError($this->Lang('encoding') . $encoding);
1142         break;
1143     }
1144     return $encoded;
1145   }
1146
1147   /**
1148    * Encode a header string to best of Q, B, quoted or none.
1149    * @access private
1150    * @return string
1151    */
1152   function EncodeHeader ($str, $position = 'text') {
1153     $x = 0;
1154
1155     switch (strtolower($position)) {
1156       case 'phrase':
1157         if (!preg_match('/[\200-\377]/', $str)) {
1158           /* Can't use addslashes as we don't know what value has magic_quotes_sybase. */
1159           $encoded = addcslashes($str, "\0..\37\177\\\"");
1160           if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
1161             return ($encoded);
1162           } else {
1163             return ("\"$encoded\"");
1164           }
1165         }
1166         $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
1167         break;
1168       case 'comment':
1169         $x = preg_match_all('/[()"]/', $str, $matches);
1170         /* Fall-through */
1171       case 'text':
1172       default:
1173         $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
1174         break;
1175     }
1176
1177     if ($x == 0) {
1178       return ($str);
1179     }
1180
1181     $maxlen = 75 - 7 - strlen($this->CharSet);
1182     /* Try to select the encoding which should produce the shortest output */
1183     if (strlen($str)/3 < $x) {
1184       $encoding = 'B';
1185       $encoded = base64_encode($str);
1186       $maxlen -= $maxlen % 4;
1187       $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
1188     } else {
1189       $encoding = 'Q';
1190       $encoded = $this->EncodeQ($str, $position);
1191       $encoded = $this->WrapText($encoded, $maxlen, true);
1192       $encoded = str_replace('='.$this->LE, "\n", trim($encoded));
1193     }
1194
1195     $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);
1196     $encoded = trim(str_replace("\n", $this->LE, $encoded));
1197
1198     return $encoded;
1199   }
1200
1201   /**
1202    * Encode string to quoted-printable.
1203    * @access private
1204    * @return string
1205    */
1206   function EncodeQP( $input = '', $line_max = 76, $space_conv = false ) {
1207     $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
1208     $lines = preg_split('/(?:\r\n|\r|\n)/', $input);
1209     $eol = "\r\n";
1210     $escape = '=';
1211     $output = '';
1212     while( list(, $line) = each($lines) ) {
1213       $linlen = strlen($line);
1214       $newline = '';
1215       for($i = 0; $i < $linlen; $i++) {
1216         $c = substr( $line, $i, 1 );
1217         $dec = ord( $c );
1218         if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E
1219           $c = '=2E';
1220         }
1221         if ( $dec == 32 ) {
1222           if ( $i == ( $linlen - 1 ) ) { // convert space at eol only
1223             $c = '=20';
1224           } else if ( $space_conv ) {
1225             $c = '=20';
1226           }
1227         } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
1228           $h2 = floor($dec/16);
1229           $h1 = floor($dec%16);
1230           $c = $escape.$hex[$h2].$hex[$h1];
1231         }
1232         if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
1233           $output .= $newline.$escape.$eol; //  soft line break; " =\r\n" is okay
1234           $newline = '';
1235           // check if newline first character will be point or not
1236           if ( $dec == 46 ) {
1237             $c = '=2E';
1238           }
1239         }
1240         $newline .= $c;
1241       } // end of for
1242       $output .= $newline.$eol;
1243     } // end of while
1244     return trim($output);
1245   }
1246
1247   /**
1248    * Encode string to q encoding.
1249    * @access private
1250    * @return string
1251    */
1252   function EncodeQ ($str, $position = 'text') {
1253     /* There should not be any EOL in the string */
1254     $encoded = preg_replace("[\r\n]", '', $str);
1255
1256     switch (strtolower($position)) {
1257       case 'phrase':
1258         $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
1259         break;
1260       case 'comment':
1261         $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
1262       case 'text':
1263       default:
1264         /* Replace every high ascii, control =, ? and _ characters */
1265         $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
1266               "'='.sprintf('%02X', ord('\\1'))", $encoded);
1267         break;
1268     }
1269
1270     /* Replace every spaces to _ (more readable than =20) */
1271     $encoded = str_replace(' ', '_', $encoded);
1272
1273     return $encoded;
1274   }
1275
1276   /**
1277    * Adds a string or binary attachment (non-filesystem) to the list.
1278    * This method can be used to attach ascii or binary data,
1279    * such as a BLOB record from a database.
1280    * @param string $string String attachment data.
1281    * @param string $filename Name of the attachment.
1282    * @param string $encoding File encoding (see $Encoding).
1283    * @param string $type File extension (MIME) type.
1284    * @return void
1285    */
1286   function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') {
1287     /* Append to $attachment array */
1288     $cur = count($this->attachment);
1289     $this->attachment[$cur][0] = $string;
1290     $this->attachment[$cur][1] = $filename;
1291     $this->attachment[$cur][2] = $filename;
1292     $this->attachment[$cur][3] = $encoding;
1293     $this->attachment[$cur][4] = $type;
1294     $this->attachment[$cur][5] = true; // isString
1295     $this->attachment[$cur][6] = 'attachment';
1296     $this->attachment[$cur][7] = 0;
1297   }
1298
1299   /**
1300    * Adds an embedded attachment.  This can include images, sounds, and
1301    * just about any other document.  Make sure to set the $type to an
1302    * image type.  For JPEG images use "image/jpeg" and for GIF images
1303    * use "image/gif".
1304    * @param string $path Path to the attachment.
1305    * @param string $cid Content ID of the attachment.  Use this to identify
1306    *        the Id for accessing the image in an HTML form.
1307    * @param string $name Overrides the attachment name.
1308    * @param string $encoding File encoding (see $Encoding).
1309    * @param string $type File extension (MIME) type.
1310    * @return bool
1311    */
1312   function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
1313
1314     if(!@is_file($path)) {
1315       $this->SetError($this->Lang('file_access') . $path);
1316       return false;
1317     }
1318
1319     $filename = basename($path);
1320     if($name == '') {
1321       $name = $filename;
1322     }
1323
1324     /* Append to $attachment array */
1325     $cur = count($this->attachment);
1326     $this->attachment[$cur][0] = $path;
1327     $this->attachment[$cur][1] = $filename;
1328     $this->attachment[$cur][2] = $name;
1329     $this->attachment[$cur][3] = $encoding;
1330     $this->attachment[$cur][4] = $type;
1331     $this->attachment[$cur][5] = false;
1332     $this->attachment[$cur][6] = 'inline';
1333     $this->attachment[$cur][7] = $cid;
1334
1335     return true;
1336   }
1337
1338   /**
1339    * Returns true if an inline attachment is present.
1340    * @access private
1341    * @return bool
1342    */
1343   function InlineImageExists() {
1344     $result = false;
1345     for($i = 0; $i < count($this->attachment); $i++) {
1346       if($this->attachment[$i][6] == 'inline') {
1347         $result = true;
1348         break;
1349       }
1350     }
1351
1352     return $result;
1353   }
1354
1355   /////////////////////////////////////////////////
1356   // CLASS METHODS, MESSAGE RESET
1357   /////////////////////////////////////////////////
1358
1359   /**
1360    * Clears all recipients assigned in the TO array.  Returns void.
1361    * @return void
1362    */
1363   function ClearAddresses() {
1364     $this->to = array();
1365   }
1366
1367   /**
1368    * Clears all recipients assigned in the CC array.  Returns void.
1369    * @return void
1370    */
1371   function ClearCCs() {
1372     $this->cc = array();
1373   }
1374
1375   /**
1376    * Clears all recipients assigned in the BCC array.  Returns void.
1377    * @return void
1378    */
1379   function ClearBCCs() {
1380     $this->bcc = array();
1381   }
1382
1383   /**
1384    * Clears all recipients assigned in the ReplyTo array.  Returns void.
1385    * @return void
1386    */
1387   function ClearReplyTos() {
1388     $this->ReplyTo = array();
1389   }
1390
1391   /**
1392    * Clears all recipients assigned in the TO, CC and BCC
1393    * array.  Returns void.
1394    * @return void
1395    */
1396   function ClearAllRecipients() {
1397     $this->to = array();
1398     $this->cc = array();
1399     $this->bcc = array();
1400   }
1401
1402   /**
1403    * Clears all previously set filesystem, string, and binary
1404    * attachments.  Returns void.
1405    * @return void
1406    */
1407   function ClearAttachments() {
1408     $this->attachment = array();
1409   }
1410
1411   /**
1412    * Clears all custom headers.  Returns void.
1413    * @return void
1414    */
1415   function ClearCustomHeaders() {
1416     $this->CustomHeader = array();
1417   }
1418
1419   /////////////////////////////////////////////////
1420   // CLASS METHODS, MISCELLANEOUS
1421   /////////////////////////////////////////////////
1422
1423   /**
1424    * Adds the error message to the error container.
1425    * Returns void.
1426    * @access private
1427    * @return void
1428    */
1429   function SetError($msg) {
1430     $this->error_count++;
1431     $this->ErrorInfo = $msg;
1432   }
1433
1434   /**
1435    * Returns the proper RFC 822 formatted date.
1436    * @access private
1437    * @return string
1438    */
1439   function RFCDate() {
1440     $tz = date('Z');
1441     $tzs = ($tz < 0) ? '-' : '+';
1442     $tz = abs($tz);
1443     $tz = (int)($tz/3600)*100 + ($tz%3600)/60;
1444     $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz);
1445
1446     return $result;
1447   }
1448
1449   /**
1450    * Returns the appropriate server variable.  Should work with both
1451    * PHP 4.1.0+ as well as older versions.  Returns an empty string
1452    * if nothing is found.
1453    * @access private
1454    * @return mixed
1455    */
1456   function ServerVar($varName) {
1457     global $HTTP_SERVER_VARS;
1458     global $HTTP_ENV_VARS;
1459
1460     if(!isset($_SERVER)) {
1461       $_SERVER = $HTTP_SERVER_VARS;
1462       if(!isset($_SERVER['REMOTE_ADDR'])) {
1463         $_SERVER = $HTTP_ENV_VARS; // must be Apache
1464       }
1465     }
1466
1467     if(isset($_SERVER[$varName])) {
1468       return $_SERVER[$varName];
1469     } else {
1470       return '';
1471     }
1472   }
1473
1474   /**
1475    * Returns the server hostname or 'localhost.localdomain' if unknown.
1476    * @access private
1477    * @return string
1478    */
1479   function ServerHostname() {
1480     if ($this->Hostname != '') {
1481       $result = $this->Hostname;
1482     } elseif ($this->ServerVar('SERVER_NAME') != '') {
1483       $result = $this->ServerVar('SERVER_NAME');
1484     } else {
1485       $result = 'localhost.localdomain';
1486     }
1487
1488     return $result;
1489   }
1490
1491   /**
1492    * Returns a message in the appropriate language.
1493    * @access private
1494    * @return string
1495    */
1496   function Lang($key) {
1497     if(count($this->language) < 1) {
1498       $this->SetLanguage('en'); // set the default language
1499     }
1500
1501     if(isset($this->language[$key])) {
1502       return $this->language[$key];
1503     } else {
1504       return 'Language string failed to load: ' . $key;
1505     }
1506   }
1507
1508   /**
1509    * Returns true if an error occurred.
1510    * @return bool
1511    */
1512   function IsError() {
1513     return ($this->error_count > 0);
1514   }
1515
1516   /**
1517    * Changes every end of line from CR or LF to CRLF.
1518    * @access private
1519    * @return string
1520    */
1521   function FixEOL($str) {
1522     $str = str_replace("\r\n", "\n", $str);
1523     $str = str_replace("\r", "\n", $str);
1524     $str = str_replace("\n", $this->LE, $str);
1525     return $str;
1526   }
1527
1528   /**
1529    * Adds a custom header.
1530    * @return void
1531    */
1532   function AddCustomHeader($custom_header) {
1533     $this->CustomHeader[] = explode(':', $custom_header, 2);
1534   }
1535
1536   /**
1537    * Evaluates the message and returns modifications for inline images and backgrounds
1538    * @access public
1539    * @return $message
1540    */
1541   function MsgHTML($message) {
1542     preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images);
1543     if(isset($images[2])) {
1544       foreach($images[2] as $i => $url) {
1545         $filename  = basename($url);
1546         $directory = dirname($url);
1547         $cid       = 'cid:' . md5($filename);
1548         $fileParts = split("\.", $filename);
1549         $ext       = $fileParts[1];
1550         $mimeType  = $this->_mime_types($ext);
1551         $message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message);
1552         $this->AddEmbeddedImage($url, md5($filename), $filename, 'base64', $mimeType);
1553       }
1554     }
1555     $this->IsHTML(true);
1556     $this->Body = $message;
1557     $textMsg = trim(strip_tags($message));
1558     if ( !empty($textMsg) && empty($this->AltBody) ) {
1559       $this->AltBody = $textMsg;
1560     }
1561     if ( empty($this->AltBody) ) {
1562       $this->AltBody = 'To view this email message, open the email in with HTML compatibility!' . "\n\n";
1563     }
1564   }
1565
1566   /**
1567    * Gets the mime type of the embedded or inline image
1568    * @access private
1569    * @return mime type of ext
1570    */
1571   function _mime_types($ext = '') {
1572     $mimes = array(
1573       'hqx'  =>  'application/mac-binhex40',
1574       'cpt'   =>  'application/mac-compactpro',
1575       'doc'   =>  'application/msword',
1576       'bin'   =>  'application/macbinary',
1577       'dms'   =>  'application/octet-stream',
1578       'lha'   =>  'application/octet-stream',
1579       'lzh'   =>  'application/octet-stream',
1580       'exe'   =>  'application/octet-stream',
1581       'class' =>  'application/octet-stream',
1582       'psd'   =>  'application/octet-stream',
1583       'so'    =>  'application/octet-stream',
1584       'sea'   =>  'application/octet-stream',
1585       'dll'   =>  'application/octet-stream',
1586       'oda'   =>  'application/oda',
1587       'pdf'   =>  'application/pdf',
1588       'ai'    =>  'application/postscript',
1589       'eps'   =>  'application/postscript',
1590       'ps'    =>  'application/postscript',
1591       'smi'   =>  'application/smil',
1592       'smil'  =>  'application/smil',
1593       'mif'   =>  'application/vnd.mif',
1594       'xls'   =>  'application/vnd.ms-excel',
1595       'ppt'   =>  'application/vnd.ms-powerpoint',
1596       'wbxml' =>  'application/vnd.wap.wbxml',
1597       'wmlc'  =>  'application/vnd.wap.wmlc',
1598       'dcr'   =>  'application/x-director',
1599       'dir'   =>  'application/x-director',
1600       'dxr'   =>  'application/x-director',
1601       'dvi'   =>  'application/x-dvi',
1602       'gtar'  =>  'application/x-gtar',
1603       'php'   =>  'application/x-httpd-php',
1604       'php4'  =>  'application/x-httpd-php',
1605       'php3'  =>  'application/x-httpd-php',
1606       'phtml' =>  'application/x-httpd-php',
1607       'phps'  =>  'application/x-httpd-php-source',
1608       'js'    =>  'application/x-javascript',
1609       'swf'   =>  'application/x-shockwave-flash',
1610       'sit'   =>  'application/x-stuffit',
1611       'tar'   =>  'application/x-tar',
1612       'tgz'   =>  'application/x-tar',
1613       'xhtml' =>  'application/xhtml+xml',
1614       'xht'   =>  'application/xhtml+xml',
1615       'zip'   =>  'application/zip',
1616       'mid'   =>  'audio/midi',
1617       'midi'  =>  'audio/midi',
1618       'mpga'  =>  'audio/mpeg',
1619       'mp2'   =>  'audio/mpeg',
1620       'mp3'   =>  'audio/mpeg',
1621       'aif'   =>  'audio/x-aiff',
1622       'aiff'  =>  'audio/x-aiff',
1623       'aifc'  =>  'audio/x-aiff',
1624       'ram'   =>  'audio/x-pn-realaudio',
1625       'rm'    =>  'audio/x-pn-realaudio',
1626       'rpm'   =>  'audio/x-pn-realaudio-plugin',
1627       'ra'    =>  'audio/x-realaudio',
1628       'rv'    =>  'video/vnd.rn-realvideo',
1629       'wav'   =>  'audio/x-wav',
1630       'bmp'   =>  'image/bmp',
1631       'gif'   =>  'image/gif',
1632       'jpeg'  =>  'image/jpeg',
1633       'jpg'   =>  'image/jpeg',
1634       'jpe'   =>  'image/jpeg',
1635       'png'   =>  'image/png',
1636       'tiff'  =>  'image/tiff',
1637       'tif'   =>  'image/tiff',
1638       'css'   =>  'text/css',
1639       'html'  =>  'text/html',
1640       'htm'   =>  'text/html',
1641       'shtml' =>  'text/html',
1642       'txt'   =>  'text/plain',
1643       'text'  =>  'text/plain',
1644       'log'   =>  'text/plain',
1645       'rtx'   =>  'text/richtext',
1646       'rtf'   =>  'text/rtf',
1647       'xml'   =>  'text/xml',
1648       'xsl'   =>  'text/xml',
1649       'mpeg'  =>  'video/mpeg',
1650       'mpg'   =>  'video/mpeg',
1651       'mpe'   =>  'video/mpeg',
1652       'qt'    =>  'video/quicktime',
1653       'mov'   =>  'video/quicktime',
1654       'avi'   =>  'video/x-msvideo',
1655       'movie' =>  'video/x-sgi-movie',
1656       'doc'   =>  'application/msword',
1657       'word'  =>  'application/msword',
1658       'xl'    =>  'application/excel',
1659       'eml'   =>  'message/rfc822'
1660     );
1661     return ( ! isset($mimes[strtolower($ext)])) ? 'application/x-unknown-content-type' : $mimes[strtolower($ext)];
1662   }
1663
1664   /**
1665    * Set (or reset) Class Objects (variables)
1666    *
1667    * Usage Example:
1668    * $page->set('X-Priority', '3');
1669    *
1670    * @access public
1671    * @param string $name Parameter Name
1672    * @param mixed $value Parameter Value
1673    * NOTE: will not work with arrays, there are no arrays to set/reset
1674    */
1675   function set ( $name, $value = '' ) {
1676     if ( isset($this->$name) ) {
1677       $this->$name = $value;
1678     } else {
1679       $this->SetError('Cannot set or reset variable ' . $name);
1680       return false;
1681     }
1682   }
1683
1684   /**
1685    * Read a file from a supplied filename and return it.
1686    *
1687    * @access public
1688    * @param string $filename Parameter File Name
1689    */
1690   function getFile($filename) {
1691     $return = '';
1692     if ($fp = fopen($filename, 'rb')) {
1693       while (!feof($fp)) {
1694         $return .= fread($fp, 1024);
1695       }
1696       fclose($fp);
1697       return $return;
1698     } else {
1699       return false;
1700     }
1701   }
1702
1703   /**
1704    * Strips newlines to prevent header injection.
1705    * @access private
1706    * @param string $str String
1707    * @return string
1708    */
1709   function SecureHeader($str) {
1710     $str = trim($str);
1711     $str = str_replace("\r", "", $str);
1712     $str = str_replace("\n", "", $str);
1713     return $str;
1714   }
1715
1716 }
1717
1718 ?>