Project

General

Profile

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
 */
20
class 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
?>
(3-3/4)