source: trunk/spip/esqueleto-redcta/plugins/zabomailmans/class/phpmailer/class.phpmailer.php @ 76

Last change on this file since 76 was 76, checked in by sebas, 16 years ago

plugin de abonomailman para enviar boletin electronico
basado sobre los cambios de sebas para arreglar los envios.

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