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