Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * The Mail_Mime class is used to create MIME E-mail messages
4
 *
5
 * The Mail_Mime class provides an OO interface to create MIME
6
 * enabled email messages. This way you can create emails that
7
 * contain plain-text bodies, HTML bodies, attachments, inline
8
 * images and specific headers.
9
 *
10
 * Compatible with PHP versions 4 and 5
11
 *
12
 * LICENSE: This LICENSE is in the BSD license style.
13
 * Copyright (c) 2002-2003, Richard Heyes <richard@phpguru.org>
14
 * Copyright (c) 2003-2006, PEAR <pear-group@php.net>
15
 * All rights reserved.
16
 *
17
 * Redistribution and use in source and binary forms, with or
18
 * without modification, are permitted provided that the following
19
 * conditions are met:
20
 *
21
 * - Redistributions of source code must retain the above copyright
22
 *   notice, this list of conditions and the following disclaimer.
23
 * - Redistributions in binary form must reproduce the above copyright
24
 *   notice, this list of conditions and the following disclaimer in the
25
 *   documentation and/or other materials provided with the distribution.
26
 * - Neither the name of the authors, nor the names of its contributors
27
 *   may be used to endorse or promote products derived from this
28
 *   software without specific prior written permission.
29
 *
30
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
34
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
40
 * THE POSSIBILITY OF SUCH DAMAGE.
41
 *
42
 * @category  Mail
43
 * @package   Mail_Mime
44
 * @author    Richard Heyes  <richard@phpguru.org>
45
 * @author    Tomas V.V. Cox <cox@idecnet.com>
46
 * @author    Cipriano Groenendal <cipri@php.net>
47
 * @author    Sean Coates <sean@php.net>
48
 * @author    Aleksander Machniak <alec@php.net>
49
 * @copyright 2003-2006 PEAR <pear-group@php.net>
50
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
51
 * @version   CVS: $Id: mime.php 305690 2010-11-23 12:41:00Z alec $
52
 * @link      http://pear.php.net/package/Mail_mime
53
 *
54
 *            This class is based on HTML Mime Mail class from
55
 *            Richard Heyes <richard@phpguru.org> which was based also
56
 *            in the mime_mail.class by Tobias Ratschiller <tobias@dnet.it>
57
 *            and Sascha Schumann <sascha@schumann.cx>
58
 */
59
 
60
 
61
/**
62
 * require PEAR
63
 *
64
 * This package depends on PEAR to raise errors.
65
 */
66
require_once 'PEAR.php';
67
 
68
/**
69
 * require Mail_mimePart
70
 *
71
 * Mail_mimePart contains the code required to
72
 * create all the different parts a mail can
73
 * consist of.
74
 */
75
require_once 'Mail/mimePart.php';
76
 
77
 
78
/**
79
 * The Mail_Mime class provides an OO interface to create MIME
80
 * enabled email messages. This way you can create emails that
81
 * contain plain-text bodies, HTML bodies, attachments, inline
82
 * images and specific headers.
83
 *
84
 * @category  Mail
85
 * @package   Mail_Mime
86
 * @author    Richard Heyes  <richard@phpguru.org>
87
 * @author    Tomas V.V. Cox <cox@idecnet.com>
88
 * @author    Cipriano Groenendal <cipri@php.net>
89
 * @author    Sean Coates <sean@php.net>
90
 * @copyright 2003-2006 PEAR <pear-group@php.net>
91
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
92
 * @version   Release: @package_version@
93
 * @link      http://pear.php.net/package/Mail_mime
94
 */
95
class Mail_mime
96
{
97
    /**
98
     * Contains the plain text part of the email
99
     *
100
     * @var string
101
     * @access private
102
     */
103
    var $_txtbody;
104
 
105
    /**
106
     * Contains the html part of the email
107
     *
108
     * @var string
109
     * @access private
110
     */
111
    var $_htmlbody;
112
 
113
    /**
114
     * list of the attached images
115
     *
116
     * @var array
117
     * @access private
118
     */
119
    var $_html_images = array();
120
 
121
    /**
122
     * list of the attachements
123
     *
124
     * @var array
125
     * @access private
126
     */
127
    var $_parts = array();
128
 
129
    /**
130
     * Headers for the mail
131
     *
132
     * @var array
133
     * @access private
134
     */
135
    var $_headers = array();
136
 
137
    /**
138
     * Build parameters
139
     *
140
     * @var array
141
     * @access private
142
     */
143
    var $_build_params = array(
144
        // What encoding to use for the headers
145
        // Options: quoted-printable or base64
146
        'head_encoding' => 'quoted-printable',
147
        // What encoding to use for plain text
148
        // Options: 7bit, 8bit, base64, or quoted-printable
149
        'text_encoding' => 'quoted-printable',
150
        // What encoding to use for html
151
        // Options: 7bit, 8bit, base64, or quoted-printable
152
        'html_encoding' => 'quoted-printable',
153
        // The character set to use for html
154
        'html_charset'  => 'ISO-8859-1',
155
        // The character set to use for text
156
        'text_charset'  => 'ISO-8859-1',
157
        // The character set to use for headers
158
        'head_charset'  => 'ISO-8859-1',
159
        // End-of-line sequence
160
        'eol'           => "\r\n",
161
        // Delay attachment files IO until building the message
162
        'delay_file_io' => false
163
    );
164
 
165
    /**
166
     * Constructor function
167
     *
168
     * @param mixed $params Build parameters that change the way the email
169
     *                      is built. Should be an associative array.
170
     *                      See $_build_params.
171
     *
172
     * @return void
173
     * @access public
174
     */
175
    function Mail_mime($params = array())
176
    {
177
        // Backward-compatible EOL setting
178
        if (is_string($params)) {
179
            $this->_build_params['eol'] = $params;
180
        } else if (defined('MAIL_MIME_CRLF') && !isset($params['eol'])) {
181
            $this->_build_params['eol'] = MAIL_MIME_CRLF;
182
        }
183
 
184
        // Update build parameters
185
        if (!empty($params) && is_array($params)) {
186
            while (list($key, $value) = each($params)) {
187
                $this->_build_params[$key] = $value;
188
            }
189
        }
190
    }
191
 
192
    /**
193
     * Set build parameter value
194
     *
195
     * @param string $name  Parameter name
196
     * @param string $value Parameter value
197
     *
198
     * @return void
199
     * @access public
200
     * @since 1.6.0
201
     */
202
    function setParam($name, $value)
203
    {
204
        $this->_build_params[$name] = $value;
205
    }
206
 
207
    /**
208
     * Get build parameter value
209
     *
210
     * @param string $name Parameter name
211
     *
212
     * @return mixed Parameter value
213
     * @access public
214
     * @since 1.6.0
215
     */
216
    function getParam($name)
217
    {
218
        return isset($this->_build_params[$name]) ? $this->_build_params[$name] : null;
219
    }
220
 
221
    /**
222
     * Accessor function to set the body text. Body text is used if
223
     * it's not an html mail being sent or else is used to fill the
224
     * text/plain part that emails clients who don't support
225
     * html should show.
226
     *
227
     * @param string $data   Either a string or
228
     *                       the file name with the contents
229
     * @param bool   $isfile If true the first param should be treated
230
     *                       as a file name, else as a string (default)
231
     * @param bool   $append If true the text or file is appended to
232
     *                       the existing body, else the old body is
233
     *                       overwritten
234
     *
235
     * @return mixed         True on success or PEAR_Error object
236
     * @access public
237
     */
238
    function setTXTBody($data, $isfile = false, $append = false)
239
    {
240
        if (!$isfile) {
241
            if (!$append) {
242
                $this->_txtbody = $data;
243
            } else {
244
                $this->_txtbody .= $data;
245
            }
246
        } else {
247
            $cont = $this->_file2str($data);
248
            if (PEAR::isError($cont)) {
249
                return $cont;
250
            }
251
            if (!$append) {
252
                $this->_txtbody = $cont;
253
            } else {
254
                $this->_txtbody .= $cont;
255
            }
256
        }
257
        return true;
258
    }
259
 
260
    /**
261
     * Get message text body
262
     *
263
     * @return string Text body
264
     * @access public
265
     * @since 1.6.0
266
     */
267
    function getTXTBody()
268
    {
269
        return $this->_txtbody;
270
    }
271
 
272
    /**
273
     * Adds a html part to the mail.
274
     *
275
     * @param string $data   Either a string or the file name with the
276
     *                       contents
277
     * @param bool   $isfile A flag that determines whether $data is a
278
     *                       filename, or a string(false, default)
279
     *
280
     * @return bool          True on success
281
     * @access public
282
     */
283
    function setHTMLBody($data, $isfile = false)
284
    {
285
        if (!$isfile) {
286
            $this->_htmlbody = $data;
287
        } else {
288
            $cont = $this->_file2str($data);
289
            if (PEAR::isError($cont)) {
290
                return $cont;
291
            }
292
            $this->_htmlbody = $cont;
293
        }
294
 
295
        return true;
296
    }
297
 
298
    /**
299
     * Get message HTML body
300
     *
301
     * @return string HTML body
302
     * @access public
303
     * @since 1.6.0
304
     */
305
    function getHTMLBody()
306
    {
307
        return $this->_htmlbody;
308
    }
309
 
310
    /**
311
     * Adds an image to the list of embedded images.
312
     *
313
     * @param string $file       The image file name OR image data itself
314
     * @param string $c_type     The content type
315
     * @param string $name       The filename of the image.
316
     *                           Only used if $file is the image data.
317
     * @param bool   $isfile     Whether $file is a filename or not.
318
     *                           Defaults to true
319
     * @param string $content_id Desired Content-ID of MIME part
320
     *                           Defaults to generated unique ID
321
     *
322
     * @return bool          True on success
323
     * @access public
324
     */
325
    function addHTMLImage($file,
326
        $c_type='application/octet-stream',
327
        $name = '',
328
        $isfile = true,
329
        $content_id = null
330
    ) {
331
        $bodyfile = null;
332
 
333
        if ($isfile) {
334
            // Don't load file into memory
335
            if ($this->_build_params['delay_file_io']) {
336
                $filedata = null;
337
                $bodyfile = $file;
338
            } else {
339
                if (PEAR::isError($filedata = $this->_file2str($file))) {
340
                    return $filedata;
341
                }
342
            }
343
            $filename = ($name ? $name : $file);
344
        } else {
345
            $filedata = $file;
346
            $filename = $name;
347
        }
348
 
349
        if (!$content_id) {
350
            $content_id = md5(uniqid(time()));
351
        }
352
 
353
        $this->_html_images[] = array(
354
            'body'      => $filedata,
355
            'body_file' => $bodyfile,
356
            'name'      => $filename,
357
            'c_type'    => $c_type,
358
            'cid'       => $content_id
359
        );
360
 
361
        return true;
362
    }
363
 
364
    /**
365
     * Adds a file to the list of attachments.
366
     *
367
     * @param string $file        The file name of the file to attach
368
     *                            or the file contents itself
369
     * @param string $c_type      The content type
370
     * @param string $name        The filename of the attachment
371
     *                            Only use if $file is the contents
372
     * @param bool   $isfile      Whether $file is a filename or not. Defaults to true
373
     * @param string $encoding    The type of encoding to use. Defaults to base64.
374
     *                            Possible values: 7bit, 8bit, base64 or quoted-printable.
375
     * @param string $disposition The content-disposition of this file
376
     *                            Defaults to attachment.
377
     *                            Possible values: attachment, inline.
378
     * @param string $charset     The character set of attachment's content.
379
     * @param string $language    The language of the attachment
380
     * @param string $location    The RFC 2557.4 location of the attachment
381
     * @param string $n_encoding  Encoding of the attachment's name in Content-Type
382
     *                            By default filenames are encoded using RFC2231 method
383
     *                            Here you can set RFC2047 encoding (quoted-printable
384
     *                            or base64) instead
385
     * @param string $f_encoding  Encoding of the attachment's filename
386
     *                            in Content-Disposition header.
387
     * @param string $description Content-Description header
388
     * @param string $h_charset   The character set of the headers e.g. filename
389
     *                            If not specified, $charset will be used
390
     *
391
     * @return mixed              True on success or PEAR_Error object
392
     * @access public
393
     */
394
    function addAttachment($file,
395
        $c_type      = 'application/octet-stream',
396
        $name        = '',
397
        $isfile      = true,
398
        $encoding    = 'base64',
399
        $disposition = 'attachment',
400
        $charset     = '',
401
        $language    = '',
402
        $location    = '',
403
        $n_encoding  = null,
404
        $f_encoding  = null,
405
        $description = '',
406
        $h_charset   = null
407
    ) {
408
        $bodyfile = null;
409
 
410
        if ($isfile) {
411
            // Don't load file into memory
412
            if ($this->_build_params['delay_file_io']) {
413
                $filedata = null;
414
                $bodyfile = $file;
415
            } else {
416
                if (PEAR::isError($filedata = $this->_file2str($file))) {
417
                    return $filedata;
418
                }
419
            }
420
            // Force the name the user supplied, otherwise use $file
421
            $filename = ($name ? $name : $file);
422
        } else {
423
            $filedata = $file;
424
            $filename = $name;
425
        }
426
 
427
        if (!strlen($filename)) {
428
            $msg = "The supplied filename for the attachment can't be empty";
429
            $err = PEAR::raiseError($msg);
430
            return $err;
431
        }
432
        $filename = $this->_basename($filename);
433
 
434
        $this->_parts[] = array(
435
            'body'        => $filedata,
436
            'body_file'   => $bodyfile,
437
            'name'        => $filename,
438
            'c_type'      => $c_type,
439
            'charset'     => $charset,
440
            'encoding'    => $encoding,
441
            'language'    => $language,
442
            'location'    => $location,
443
            'disposition' => $disposition,
444
            'description' => $description,
445
            'name_encoding'     => $n_encoding,
446
            'filename_encoding' => $f_encoding,
447
            'headers_charset'   => $h_charset,
448
        );
449
 
450
        return true;
451
    }
452
 
453
    /**
454
     * Get the contents of the given file name as string
455
     *
456
     * @param string $file_name Path of file to process
457
     *
458
     * @return string           Contents of $file_name
459
     * @access private
460
     */
461
    function &_file2str($file_name)
462
    {
463
        // Check state of file and raise an error properly
464
        if (!file_exists($file_name)) {
465
            $err = PEAR::raiseError('File not found: ' . $file_name);
466
            return $err;
467
        }
468
        if (!is_file($file_name)) {
469
            $err = PEAR::raiseError('Not a regular file: ' . $file_name);
470
            return $err;
471
        }
472
        if (!is_readable($file_name)) {
473
            $err = PEAR::raiseError('File is not readable: ' . $file_name);
474
            return $err;
475
        }
476
 
477
        // Temporarily reset magic_quotes_runtime and read file contents
478
        if ($magic_quote_setting = get_magic_quotes_runtime()) {
479
            @ini_set('magic_quotes_runtime', 0);
480
        }
481
        $cont = file_get_contents($file_name);
482
        if ($magic_quote_setting) {
483
            @ini_set('magic_quotes_runtime', $magic_quote_setting);
484
        }
485
 
486
        return $cont;
487
    }
488
 
489
    /**
490
     * Adds a text subpart to the mimePart object and
491
     * returns it during the build process.
492
     *
493
     * @param mixed  &$obj The object to add the part to, or
494
     *                     null if a new object is to be created.
495
     * @param string $text The text to add.
496
     *
497
     * @return object      The text mimePart object
498
     * @access private
499
     */
500
    function &_addTextPart(&$obj, $text)
501
    {
502
        $params['content_type'] = 'text/plain';
503
        $params['encoding']     = $this->_build_params['text_encoding'];
504
        $params['charset']      = $this->_build_params['text_charset'];
505
        $params['eol']          = $this->_build_params['eol'];
506
 
507
        if (is_object($obj)) {
508
            $ret = $obj->addSubpart($text, $params);
509
            return $ret;
510
        } else {
511
            $ret = new Mail_mimePart($text, $params);
512
            return $ret;
513
        }
514
    }
515
 
516
    /**
517
     * Adds a html subpart to the mimePart object and
518
     * returns it during the build process.
519
     *
520
     * @param mixed &$obj The object to add the part to, or
521
     *                    null if a new object is to be created.
522
     *
523
     * @return object     The html mimePart object
524
     * @access private
525
     */
526
    function &_addHtmlPart(&$obj)
527
    {
528
        $params['content_type'] = 'text/html';
529
        $params['encoding']     = $this->_build_params['html_encoding'];
530
        $params['charset']      = $this->_build_params['html_charset'];
531
        $params['eol']          = $this->_build_params['eol'];
532
 
533
        if (is_object($obj)) {
534
            $ret = $obj->addSubpart($this->_htmlbody, $params);
535
            return $ret;
536
        } else {
537
            $ret = new Mail_mimePart($this->_htmlbody, $params);
538
            return $ret;
539
        }
540
    }
541
 
542
    /**
543
     * Creates a new mimePart object, using multipart/mixed as
544
     * the initial content-type and returns it during the
545
     * build process.
546
     *
547
     * @return object The multipart/mixed mimePart object
548
     * @access private
549
     */
550
    function &_addMixedPart()
551
    {
552
        $params                 = array();
553
        $params['content_type'] = 'multipart/mixed';
554
        $params['eol']          = $this->_build_params['eol'];
555
 
556
        // Create empty multipart/mixed Mail_mimePart object to return
557
        $ret = new Mail_mimePart('', $params);
558
        return $ret;
559
    }
560
 
561
    /**
562
     * Adds a multipart/alternative part to a mimePart
563
     * object (or creates one), and returns it during
564
     * the build process.
565
     *
566
     * @param mixed &$obj The object to add the part to, or
567
     *                    null if a new object is to be created.
568
     *
569
     * @return object     The multipart/mixed mimePart object
570
     * @access private
571
     */
572
    function &_addAlternativePart(&$obj)
573
    {
574
        $params['content_type'] = 'multipart/alternative';
575
        $params['eol']          = $this->_build_params['eol'];
576
 
577
        if (is_object($obj)) {
578
            return $obj->addSubpart('', $params);
579
        } else {
580
            $ret = new Mail_mimePart('', $params);
581
            return $ret;
582
        }
583
    }
584
 
585
    /**
586
     * Adds a multipart/related part to a mimePart
587
     * object (or creates one), and returns it during
588
     * the build process.
589
     *
590
     * @param mixed &$obj The object to add the part to, or
591
     *                    null if a new object is to be created
592
     *
593
     * @return object     The multipart/mixed mimePart object
594
     * @access private
595
     */
596
    function &_addRelatedPart(&$obj)
597
    {
598
        $params['content_type'] = 'multipart/related';
599
        $params['eol']          = $this->_build_params['eol'];
600
 
601
        if (is_object($obj)) {
602
            return $obj->addSubpart('', $params);
603
        } else {
604
            $ret = new Mail_mimePart('', $params);
605
            return $ret;
606
        }
607
    }
608
 
609
    /**
610
     * Adds an html image subpart to a mimePart object
611
     * and returns it during the build process.
612
     *
613
     * @param object &$obj  The mimePart to add the image to
614
     * @param array  $value The image information
615
     *
616
     * @return object       The image mimePart object
617
     * @access private
618
     */
619
    function &_addHtmlImagePart(&$obj, $value)
620
    {
621
        $params['content_type'] = $value['c_type'];
622
        $params['encoding']     = 'base64';
623
        $params['disposition']  = 'inline';
624
        $params['filename']     = $value['name'];
625
        $params['cid']          = $value['cid'];
626
        $params['body_file']    = $value['body_file'];
627
        $params['eol']          = $this->_build_params['eol'];
628
 
629
        if (!empty($value['name_encoding'])) {
630
            $params['name_encoding'] = $value['name_encoding'];
631
        }
632
        if (!empty($value['filename_encoding'])) {
633
            $params['filename_encoding'] = $value['filename_encoding'];
634
        }
635
 
636
        $ret = $obj->addSubpart($value['body'], $params);
637
        return $ret;
638
    }
639
 
640
    /**
641
     * Adds an attachment subpart to a mimePart object
642
     * and returns it during the build process.
643
     *
644
     * @param object &$obj  The mimePart to add the image to
645
     * @param array  $value The attachment information
646
     *
647
     * @return object       The image mimePart object
648
     * @access private
649
     */
650
    function &_addAttachmentPart(&$obj, $value)
651
    {
652
        $params['eol']          = $this->_build_params['eol'];
653
        $params['filename']     = $value['name'];
654
        $params['encoding']     = $value['encoding'];
655
        $params['content_type'] = $value['c_type'];
656
        $params['body_file']    = $value['body_file'];
657
        $params['disposition']  = isset($value['disposition']) ?
658
                                  $value['disposition'] : 'attachment';
659
 
660
        // content charset
661
        if (!empty($value['charset'])) {
662
            $params['charset'] = $value['charset'];
663
        }
664
        // headers charset (filename, description)
665
        if (!empty($value['headers_charset'])) {
666
            $params['headers_charset'] = $value['headers_charset'];
667
        }
668
        if (!empty($value['language'])) {
669
            $params['language'] = $value['language'];
670
        }
671
        if (!empty($value['location'])) {
672
            $params['location'] = $value['location'];
673
        }
674
        if (!empty($value['name_encoding'])) {
675
            $params['name_encoding'] = $value['name_encoding'];
676
        }
677
        if (!empty($value['filename_encoding'])) {
678
            $params['filename_encoding'] = $value['filename_encoding'];
679
        }
680
        if (!empty($value['description'])) {
681
            $params['description'] = $value['description'];
682
        }
683
 
684
        $ret = $obj->addSubpart($value['body'], $params);
685
        return $ret;
686
    }
687
 
688
    /**
689
     * Returns the complete e-mail, ready to send using an alternative
690
     * mail delivery method. Note that only the mailpart that is made
691
     * with Mail_Mime is created. This means that,
692
     * YOU WILL HAVE NO TO: HEADERS UNLESS YOU SET IT YOURSELF
693
     * using the $headers parameter!
694
     *
695
     * @param string $separation The separation between these two parts.
696
     * @param array  $params     The Build parameters passed to the
697
     *                           &get() function. See &get for more info.
698
     * @param array  $headers    The extra headers that should be passed
699
     *                           to the &headers() function.
700
     *                           See that function for more info.
701
     * @param bool   $overwrite  Overwrite the existing headers with new.
702
     *
703
     * @return mixed The complete e-mail or PEAR error object
704
     * @access public
705
     */
706
    function getMessage($separation = null, $params = null, $headers = null,
707
        $overwrite = false
708
    ) {
709
        if ($separation === null) {
710
            $separation = $this->_build_params['eol'];
711
        }
712
 
713
        $body = $this->get($params);
714
 
715
        if (PEAR::isError($body)) {
716
            return $body;
717
        }
718
 
719
        $head = $this->txtHeaders($headers, $overwrite);
720
        $mail = $head . $separation . $body;
721
        return $mail;
722
    }
723
 
724
    /**
725
     * Returns the complete e-mail body, ready to send using an alternative
726
     * mail delivery method.
727
     *
728
     * @param array $params The Build parameters passed to the
729
     *                      &get() function. See &get for more info.
730
     *
731
     * @return mixed The e-mail body or PEAR error object
732
     * @access public
733
     * @since 1.6.0
734
     */
735
    function getMessageBody($params = null)
736
    {
737
        return $this->get($params, null, true);
738
    }
739
 
740
    /**
741
     * Writes (appends) the complete e-mail into file.
742
     *
743
     * @param string $filename  Output file location
744
     * @param array  $params    The Build parameters passed to the
745
     *                          &get() function. See &get for more info.
746
     * @param array  $headers   The extra headers that should be passed
747
     *                          to the &headers() function.
748
     *                          See that function for more info.
749
     * @param bool   $overwrite Overwrite the existing headers with new.
750
     *
751
     * @return mixed True or PEAR error object
752
     * @access public
753
     * @since 1.6.0
754
     */
755
    function saveMessage($filename, $params = null, $headers = null, $overwrite = false)
756
    {
757
        // Check state of file and raise an error properly
758
        if (file_exists($filename) && !is_writable($filename)) {
759
            $err = PEAR::raiseError('File is not writable: ' . $filename);
760
            return $err;
761
        }
762
 
763
        // Temporarily reset magic_quotes_runtime and read file contents
764
        if ($magic_quote_setting = get_magic_quotes_runtime()) {
765
            @ini_set('magic_quotes_runtime', 0);
766
        }
767
 
768
        if (!($fh = fopen($filename, 'ab'))) {
769
            $err = PEAR::raiseError('Unable to open file: ' . $filename);
770
            return $err;
771
        }
772
 
773
        // Write message headers into file (skipping Content-* headers)
774
        $head = $this->txtHeaders($headers, $overwrite, true);
775
        if (fwrite($fh, $head) === false) {
776
            $err = PEAR::raiseError('Error writing to file: ' . $filename);
777
            return $err;
778
        }
779
 
780
        fclose($fh);
781
 
782
        if ($magic_quote_setting) {
783
            @ini_set('magic_quotes_runtime', $magic_quote_setting);
784
        }
785
 
786
        // Write the rest of the message into file
787
        $res = $this->get($params, $filename);
788
 
789
        return $res ? $res : true;
790
    }
791
 
792
    /**
793
     * Writes (appends) the complete e-mail body into file.
794
     *
795
     * @param string $filename Output file location
796
     * @param array  $params   The Build parameters passed to the
797
     *                         &get() function. See &get for more info.
798
     *
799
     * @return mixed True or PEAR error object
800
     * @access public
801
     * @since 1.6.0
802
     */
803
    function saveMessageBody($filename, $params = null)
804
    {
805
        // Check state of file and raise an error properly
806
        if (file_exists($filename) && !is_writable($filename)) {
807
            $err = PEAR::raiseError('File is not writable: ' . $filename);
808
            return $err;
809
        }
810
 
811
        // Temporarily reset magic_quotes_runtime and read file contents
812
        if ($magic_quote_setting = get_magic_quotes_runtime()) {
813
            @ini_set('magic_quotes_runtime', 0);
814
        }
815
 
816
        if (!($fh = fopen($filename, 'ab'))) {
817
            $err = PEAR::raiseError('Unable to open file: ' . $filename);
818
            return $err;
819
        }
820
 
821
        // Write the rest of the message into file
822
        $res = $this->get($params, $filename, true);
823
 
824
        return $res ? $res : true;
825
    }
826
 
827
    /**
828
     * Builds the multipart message from the list ($this->_parts) and
829
     * returns the mime content.
830
     *
831
     * @param array    $params    Build parameters that change the way the email
832
     *                            is built. Should be associative. See $_build_params.
833
     * @param resource $filename  Output file where to save the message instead of
834
     *                            returning it
835
     * @param boolean  $skip_head True if you want to return/save only the message
836
     *                            without headers
837
     *
838
     * @return mixed The MIME message content string, null or PEAR error object
839
     * @access public
840
     */
841
    function &get($params = null, $filename = null, $skip_head = false)
842
    {
843
        if (isset($params)) {
844
            while (list($key, $value) = each($params)) {
845
                $this->_build_params[$key] = $value;
846
            }
847
        }
848
 
849
        if (isset($this->_headers['From'])) {
850
            // Bug #11381: Illegal characters in domain ID
851
            if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $this->_headers['From'], $matches)) {
852
                $domainID = $matches[1];
853
            } else {
854
                $domainID = '@localhost';
855
            }
856
            foreach ($this->_html_images as $i => $img) {
857
                $cid = $this->_html_images[$i]['cid'];
858
                if (!preg_match('#'.preg_quote($domainID).'$#', $cid)) {
859
                    $this->_html_images[$i]['cid'] = $cid . $domainID;
860
                }
861
            }
862
        }
863
 
864
        if (count($this->_html_images) && isset($this->_htmlbody)) {
865
            foreach ($this->_html_images as $key => $value) {
866
                $regex   = array();
867
                $regex[] = '#(\s)((?i)src|background|href(?-i))\s*=\s*(["\']?)' .
868
                            preg_quote($value['name'], '#') . '\3#';
869
                $regex[] = '#(?i)url(?-i)\(\s*(["\']?)' .
870
                            preg_quote($value['name'], '#') . '\1\s*\)#';
871
 
872
                $rep   = array();
873
                $rep[] = '\1\2=\3cid:' . $value['cid'] .'\3';
874
                $rep[] = 'url(\1cid:' . $value['cid'] . '\1)';
875
 
876
                $this->_htmlbody = preg_replace($regex, $rep, $this->_htmlbody);
877
                $this->_html_images[$key]['name']
878
                    = $this->_basename($this->_html_images[$key]['name']);
879
            }
880
        }
881
 
882
        $this->_checkParams();
883
 
884
        $null        = null;
885
        $attachments = count($this->_parts)                 ? true : false;
886
        $html_images = count($this->_html_images)           ? true : false;
887
        $html        = strlen($this->_htmlbody)             ? true : false;
888
        $text        = (!$html && strlen($this->_txtbody))  ? true : false;
889
 
890
        switch (true) {
891
        case $text && !$attachments:
892
            $message =& $this->_addTextPart($null, $this->_txtbody);
893
            break;
894
 
895
        case !$text && !$html && $attachments:
896
            $message =& $this->_addMixedPart();
897
            for ($i = 0; $i < count($this->_parts); $i++) {
898
                $this->_addAttachmentPart($message, $this->_parts[$i]);
899
            }
900
            break;
901
 
902
        case $text && $attachments:
903
            $message =& $this->_addMixedPart();
904
            $this->_addTextPart($message, $this->_txtbody);
905
            for ($i = 0; $i < count($this->_parts); $i++) {
906
                $this->_addAttachmentPart($message, $this->_parts[$i]);
907
            }
908
            break;
909
 
910
        case $html && !$attachments && !$html_images:
911
            if (isset($this->_txtbody)) {
912
                $message =& $this->_addAlternativePart($null);
913
                $this->_addTextPart($message, $this->_txtbody);
914
                $this->_addHtmlPart($message);
915
            } else {
916
                $message =& $this->_addHtmlPart($null);
917
            }
918
            break;
919
 
920
        case $html && !$attachments && $html_images:
921
            // * Content-Type: multipart/alternative;
922
            //    * text
923
            //    * Content-Type: multipart/related;
924
            //       * html
925
            //       * image...
926
            if (isset($this->_txtbody)) {
927
                $message =& $this->_addAlternativePart($null);
928
                $this->_addTextPart($message, $this->_txtbody);
929
 
930
                $ht =& $this->_addRelatedPart($message);
931
                $this->_addHtmlPart($ht);
932
                for ($i = 0; $i < count($this->_html_images); $i++) {
933
                    $this->_addHtmlImagePart($ht, $this->_html_images[$i]);
934
                }
935
            } else {
936
                // * Content-Type: multipart/related;
937
                //    * html
938
                //    * image...
939
                $message =& $this->_addRelatedPart($null);
940
                $this->_addHtmlPart($message);
941
                for ($i = 0; $i < count($this->_html_images); $i++) {
942
                    $this->_addHtmlImagePart($message, $this->_html_images[$i]);
943
                }
944
            }
945
            /*
946
            // #13444, #9725: the code below was a non-RFC compliant hack
947
            // * Content-Type: multipart/related;
948
            //    * Content-Type: multipart/alternative;
949
            //        * text
950
            //        * html
951
            //    * image...
952
            $message =& $this->_addRelatedPart($null);
953
            if (isset($this->_txtbody)) {
954
                $alt =& $this->_addAlternativePart($message);
955
                $this->_addTextPart($alt, $this->_txtbody);
956
                $this->_addHtmlPart($alt);
957
            } else {
958
                $this->_addHtmlPart($message);
959
            }
960
            for ($i = 0; $i < count($this->_html_images); $i++) {
961
                $this->_addHtmlImagePart($message, $this->_html_images[$i]);
962
            }
963
            */
964
            break;
965
 
966
        case $html && $attachments && !$html_images:
967
            $message =& $this->_addMixedPart();
968
            if (isset($this->_txtbody)) {
969
                $alt =& $this->_addAlternativePart($message);
970
                $this->_addTextPart($alt, $this->_txtbody);
971
                $this->_addHtmlPart($alt);
972
            } else {
973
                $this->_addHtmlPart($message);
974
            }
975
            for ($i = 0; $i < count($this->_parts); $i++) {
976
                $this->_addAttachmentPart($message, $this->_parts[$i]);
977
            }
978
            break;
979
 
980
        case $html && $attachments && $html_images:
981
            $message =& $this->_addMixedPart();
982
            if (isset($this->_txtbody)) {
983
                $alt =& $this->_addAlternativePart($message);
984
                $this->_addTextPart($alt, $this->_txtbody);
985
                $rel =& $this->_addRelatedPart($alt);
986
            } else {
987
                $rel =& $this->_addRelatedPart($message);
988
            }
989
            $this->_addHtmlPart($rel);
990
            for ($i = 0; $i < count($this->_html_images); $i++) {
991
                $this->_addHtmlImagePart($rel, $this->_html_images[$i]);
992
            }
993
            for ($i = 0; $i < count($this->_parts); $i++) {
994
                $this->_addAttachmentPart($message, $this->_parts[$i]);
995
            }
996
            break;
997
 
998
        }
999
 
1000
        if (!isset($message)) {
1001
            $ret = null;
1002
            return $ret;
1003
        }
1004
 
1005
        // Use saved boundary
1006
        if (!empty($this->_build_params['boundary'])) {
1007
            $boundary = $this->_build_params['boundary'];
1008
        } else {
1009
            $boundary = null;
1010
        }
1011
 
1012
        // Write output to file
1013
        if ($filename) {
1014
            // Append mimePart message headers and body into file
1015
            $headers = $message->encodeToFile($filename, $boundary, $skip_head);
1016
            if (PEAR::isError($headers)) {
1017
                return $headers;
1018
            }
1019
            $this->_headers = array_merge($this->_headers, $headers);
1020
            $ret = null;
1021
            return $ret;
1022
        } else {
1023
            $output = $message->encode($boundary, $skip_head);
1024
            if (PEAR::isError($output)) {
1025
                return $output;
1026
            }
1027
            $this->_headers = array_merge($this->_headers, $output['headers']);
1028
            $body = $output['body'];
1029
            return $body;
1030
        }
1031
    }
1032
 
1033
    /**
1034
     * Returns an array with the headers needed to prepend to the email
1035
     * (MIME-Version and Content-Type). Format of argument is:
1036
     * $array['header-name'] = 'header-value';
1037
     *
1038
     * @param array $xtra_headers Assoc array with any extra headers (optional)
1039
     *                            (Don't set Content-Type for multipart messages here!)
1040
     * @param bool  $overwrite    Overwrite already existing headers.
1041
     * @param bool  $skip_content Don't return content headers: Content-Type,
1042
     *                            Content-Disposition and Content-Transfer-Encoding
1043
     *
1044
     * @return array              Assoc array with the mime headers
1045
     * @access public
1046
     */
1047
    function &headers($xtra_headers = null, $overwrite = false, $skip_content = false)
1048
    {
1049
        // Add mime version header
1050
        $headers['MIME-Version'] = '1.0';
1051
 
1052
        // Content-Type and Content-Transfer-Encoding headers should already
1053
        // be present if get() was called, but we'll re-set them to make sure
1054
        // we got them when called before get() or something in the message
1055
        // has been changed after get() [#14780]
1056
        if (!$skip_content) {
1057
            $headers += $this->_contentHeaders();
1058
        }
1059
 
1060
        if (!empty($xtra_headers)) {
1061
            $headers = array_merge($headers, $xtra_headers);
1062
        }
1063
 
1064
        if ($overwrite) {
1065
            $this->_headers = array_merge($this->_headers, $headers);
1066
        } else {
1067
            $this->_headers = array_merge($headers, $this->_headers);
1068
        }
1069
 
1070
        $headers = $this->_headers;
1071
 
1072
        if ($skip_content) {
1073
            unset($headers['Content-Type']);
1074
            unset($headers['Content-Transfer-Encoding']);
1075
            unset($headers['Content-Disposition']);
1076
        } else if (!empty($this->_build_params['ctype'])) {
1077
            $headers['Content-Type'] = $this->_build_params['ctype'];
1078
        }
1079
 
1080
        $encodedHeaders = $this->_encodeHeaders($headers);
1081
        return $encodedHeaders;
1082
    }
1083
 
1084
    /**
1085
     * Get the text version of the headers
1086
     * (usefull if you want to use the PHP mail() function)
1087
     *
1088
     * @param array $xtra_headers Assoc array with any extra headers (optional)
1089
     *                            (Don't set Content-Type for multipart messages here!)
1090
     * @param bool  $overwrite    Overwrite the existing headers with new.
1091
     * @param bool  $skip_content Don't return content headers: Content-Type,
1092
     *                            Content-Disposition and Content-Transfer-Encoding
1093
     *
1094
     * @return string             Plain text headers
1095
     * @access public
1096
     */
1097
    function txtHeaders($xtra_headers = null, $overwrite = false, $skip_content = false)
1098
    {
1099
        $headers = $this->headers($xtra_headers, $overwrite, $skip_content);
1100
 
1101
        // Place Received: headers at the beginning of the message
1102
        // Spam detectors often flag messages with it after the Subject: as spam
1103
        if (isset($headers['Received'])) {
1104
            $received = $headers['Received'];
1105
            unset($headers['Received']);
1106
            $headers = array('Received' => $received) + $headers;
1107
        }
1108
 
1109
        $ret = '';
1110
        $eol = $this->_build_params['eol'];
1111
 
1112
        foreach ($headers as $key => $val) {
1113
            if (is_array($val)) {
1114
                foreach ($val as $value) {
1115
                    $ret .= "$key: $value" . $eol;
1116
                }
1117
            } else {
1118
                $ret .= "$key: $val" . $eol;
1119
            }
1120
        }
1121
 
1122
        return $ret;
1123
    }
1124
 
1125
    /**
1126
     * Sets message Content-Type header.
1127
     * Use it to build messages with various content-types e.g. miltipart/raport
1128
     * not supported by _contentHeaders() function.
1129
     *
1130
     * @param string $type   Type name
1131
     * @param array  $params Hash array of header parameters
1132
     *
1133
     * @return void
1134
     * @access public
1135
     * @since 1.7.0
1136
     */
1137
    function setContentType($type, $params = array())
1138
    {
1139
        $header = $type;
1140
 
1141
        $eol = !empty($this->_build_params['eol'])
1142
            ? $this->_build_params['eol'] : "\r\n";
1143
 
1144
        // add parameters
1145
        $token_regexp = '#([^\x21,\x23-\x27,\x2A,\x2B,\x2D'
1146
            . ',\x2E,\x30-\x39,\x41-\x5A,\x5E-\x7E])#';
1147
        if (is_array($params)) {
1148
            foreach ($params as $name => $value) {
1149
                if ($name == 'boundary') {
1150
                    $this->_build_params['boundary'] = $value;
1151
                }
1152
                if (!preg_match($token_regexp, $value)) {
1153
                    $header .= ";$eol $name=$value";
1154
                } else {
1155
                    $value = addcslashes($value, '\\"');
1156
                    $header .= ";$eol $name=\"$value\"";
1157
                }
1158
            }
1159
        }
1160
 
1161
        // add required boundary parameter if not defined
1162
        if (preg_match('/^multipart\//i', $type)) {
1163
            if (empty($this->_build_params['boundary'])) {
1164
                $this->_build_params['boundary'] = '=_' . md5(rand() . microtime());
1165
            }
1166
 
1167
            $header .= ";$eol boundary=\"".$this->_build_params['boundary']."\"";
1168
        }
1169
 
1170
        $this->_build_params['ctype'] = $header;
1171
    }
1172
 
1173
    /**
1174
     * Sets the Subject header
1175
     *
1176
     * @param string $subject String to set the subject to.
1177
     *
1178
     * @return void
1179
     * @access public
1180
     */
1181
    function setSubject($subject)
1182
    {
1183
        $this->_headers['Subject'] = $subject;
1184
    }
1185
 
1186
    /**
1187
     * Set an email to the From (the sender) header
1188
     *
1189
     * @param string $email The email address to use
1190
     *
1191
     * @return void
1192
     * @access public
1193
     */
1194
    function setFrom($email)
1195
    {
1196
        $this->_headers['From'] = $email;
1197
    }
1198
 
1199
    /**
1200
     * Add an email to the To header
1201
     * (multiple calls to this method are allowed)
1202
     *
1203
     * @param string $email The email direction to add
1204
     *
1205
     * @return void
1206
     * @access public
1207
     */
1208
    function addTo($email)
1209
    {
1210
        if (isset($this->_headers['To'])) {
1211
            $this->_headers['To'] .= ", $email";
1212
        } else {
1213
            $this->_headers['To'] = $email;
1214
        }
1215
    }
1216
 
1217
    /**
1218
     * Add an email to the Cc (carbon copy) header
1219
     * (multiple calls to this method are allowed)
1220
     *
1221
     * @param string $email The email direction to add
1222
     *
1223
     * @return void
1224
     * @access public
1225
     */
1226
    function addCc($email)
1227
    {
1228
        if (isset($this->_headers['Cc'])) {
1229
            $this->_headers['Cc'] .= ", $email";
1230
        } else {
1231
            $this->_headers['Cc'] = $email;
1232
        }
1233
    }
1234
 
1235
    /**
1236
     * Add an email to the Bcc (blank carbon copy) header
1237
     * (multiple calls to this method are allowed)
1238
     *
1239
     * @param string $email The email direction to add
1240
     *
1241
     * @return void
1242
     * @access public
1243
     */
1244
    function addBcc($email)
1245
    {
1246
        if (isset($this->_headers['Bcc'])) {
1247
            $this->_headers['Bcc'] .= ", $email";
1248
        } else {
1249
            $this->_headers['Bcc'] = $email;
1250
        }
1251
    }
1252
 
1253
    /**
1254
     * Since the PHP send function requires you to specify
1255
     * recipients (To: header) separately from the other
1256
     * headers, the To: header is not properly encoded.
1257
     * To fix this, you can use this public method to
1258
     * encode your recipients before sending to the send
1259
     * function
1260
     *
1261
     * @param string $recipients A comma-delimited list of recipients
1262
     *
1263
     * @return string            Encoded data
1264
     * @access public
1265
     */
1266
    function encodeRecipients($recipients)
1267
    {
1268
        $input = array("To" => $recipients);
1269
        $retval = $this->_encodeHeaders($input);
1270
        return $retval["To"] ;
1271
    }
1272
 
1273
    /**
1274
     * Encodes headers as per RFC2047
1275
     *
1276
     * @param array $input  The header data to encode
1277
     * @param array $params Extra build parameters
1278
     *
1279
     * @return array        Encoded data
1280
     * @access private
1281
     */
1282
    function _encodeHeaders($input, $params = array())
1283
    {
1284
        $build_params = $this->_build_params;
1285
        while (list($key, $value) = each($params)) {
1286
            $build_params[$key] = $value;
1287
        }
1288
 
1289
        foreach ($input as $hdr_name => $hdr_value) {
1290
            if (is_array($hdr_value)) {
1291
                foreach ($hdr_value as $idx => $value) {
1292
                    $input[$hdr_name][$idx] = $this->encodeHeader(
1293
                        $hdr_name, $value,
1294
                        $build_params['head_charset'], $build_params['head_encoding']
1295
                    );
1296
                }
1297
            } else {
1298
                $input[$hdr_name] = $this->encodeHeader(
1299
                    $hdr_name, $hdr_value,
1300
                    $build_params['head_charset'], $build_params['head_encoding']
1301
                );
1302
            }
1303
        }
1304
 
1305
        return $input;
1306
    }
1307
 
1308
    /**
1309
     * Encodes a header as per RFC2047
1310
     *
1311
     * @param string $name     The header name
1312
     * @param string $value    The header data to encode
1313
     * @param string $charset  Character set name
1314
     * @param string $encoding Encoding name (base64 or quoted-printable)
1315
     *
1316
     * @return string          Encoded header data (without a name)
1317
     * @access public
1318
     * @since 1.5.3
1319
     */
1320
    function encodeHeader($name, $value, $charset, $encoding)
1321
    {
1322
        return Mail_mimePart::encodeHeader(
1323
            $name, $value, $charset, $encoding, $this->_build_params['eol']
1324
        );
1325
    }
1326
 
1327
    /**
1328
     * Get file's basename (locale independent)
1329
     *
1330
     * @param string $filename Filename
1331
     *
1332
     * @return string          Basename
1333
     * @access private
1334
     */
1335
    function _basename($filename)
1336
    {
1337
        // basename() is not unicode safe and locale dependent
1338
        if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) {
1339
            return preg_replace('/^.*[\\\\\\/]/', '', $filename);
1340
        } else {
1341
            return preg_replace('/^.*[\/]/', '', $filename);
1342
        }
1343
    }
1344
 
1345
    /**
1346
     * Get Content-Type and Content-Transfer-Encoding headers of the message
1347
     *
1348
     * @return array Headers array
1349
     * @access private
1350
     */
1351
    function _contentHeaders()
1352
    {
1353
        $attachments = count($this->_parts)                 ? true : false;
1354
        $html_images = count($this->_html_images)           ? true : false;
1355
        $html        = strlen($this->_htmlbody)             ? true : false;
1356
        $text        = (!$html && strlen($this->_txtbody))  ? true : false;
1357
        $headers     = array();
1358
 
1359
        // See get()
1360
        switch (true) {
1361
        case $text && !$attachments:
1362
            $headers['Content-Type'] = 'text/plain';
1363
            break;
1364
 
1365
        case !$text && !$html && $attachments:
1366
        case $text && $attachments:
1367
        case $html && $attachments && !$html_images:
1368
        case $html && $attachments && $html_images:
1369
            $headers['Content-Type'] = 'multipart/mixed';
1370
            break;
1371
 
1372
        case $html && !$attachments && !$html_images && isset($this->_txtbody):
1373
        case $html && !$attachments && $html_images && isset($this->_txtbody):
1374
            $headers['Content-Type'] = 'multipart/alternative';
1375
            break;
1376
 
1377
        case $html && !$attachments && !$html_images && !isset($this->_txtbody):
1378
            $headers['Content-Type'] = 'text/html';
1379
            break;
1380
 
1381
        case $html && !$attachments && $html_images && !isset($this->_txtbody):
1382
            $headers['Content-Type'] = 'multipart/related';
1383
            break;
1384
 
1385
        default:
1386
            return $headers;
1387
        }
1388
 
1389
        $this->_checkParams();
1390
 
1391
        $eol = !empty($this->_build_params['eol'])
1392
            ? $this->_build_params['eol'] : "\r\n";
1393
 
1394
        if ($headers['Content-Type'] == 'text/plain') {
1395
            // single-part message: add charset and encoding
1396
            $charset = 'charset=' . $this->_build_params['text_charset'];
1397
            // place charset parameter in the same line, if possible
1398
            // 26 = strlen("Content-Type: text/plain; ")
1399
            $headers['Content-Type']
1400
                .= (strlen($charset) + 26 <= 76) ? "; $charset" : ";$eol $charset";
1401
            $headers['Content-Transfer-Encoding']
1402
                = $this->_build_params['text_encoding'];
1403
        } else if ($headers['Content-Type'] == 'text/html') {
1404
            // single-part message: add charset and encoding
1405
            $charset = 'charset=' . $this->_build_params['html_charset'];
1406
            // place charset parameter in the same line, if possible
1407
            $headers['Content-Type']
1408
                .= (strlen($charset) + 25 <= 76) ? "; $charset" : ";$eol $charset";
1409
            $headers['Content-Transfer-Encoding']
1410
                = $this->_build_params['html_encoding'];
1411
        } else {
1412
            // multipart message: and boundary
1413
            if (!empty($this->_build_params['boundary'])) {
1414
                $boundary = $this->_build_params['boundary'];
1415
            } else if (!empty($this->_headers['Content-Type'])
1416
                && preg_match('/boundary="([^"]+)"/', $this->_headers['Content-Type'], $m)
1417
            ) {
1418
                $boundary = $m[1];
1419
            } else {
1420
                $boundary = '=_' . md5(rand() . microtime());
1421
            }
1422
 
1423
            $this->_build_params['boundary'] = $boundary;
1424
            $headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
1425
        }
1426
 
1427
        return $headers;
1428
    }
1429
 
1430
    /**
1431
     * Validate and set build parameters
1432
     *
1433
     * @return void
1434
     * @access private
1435
     */
1436
    function _checkParams()
1437
    {
1438
        $encodings = array('7bit', '8bit', 'base64', 'quoted-printable');
1439
 
1440
        $this->_build_params['text_encoding']
1441
            = strtolower($this->_build_params['text_encoding']);
1442
        $this->_build_params['html_encoding']
1443
            = strtolower($this->_build_params['html_encoding']);
1444
 
1445
        if (!in_array($this->_build_params['text_encoding'], $encodings)) {
1446
            $this->_build_params['text_encoding'] = '7bit';
1447
        }
1448
        if (!in_array($this->_build_params['html_encoding'], $encodings)) {
1449
            $this->_build_params['html_encoding'] = '7bit';
1450
        }
1451
 
1452
        // text body
1453
        if ($this->_build_params['text_encoding'] == '7bit'
1454
            && !preg_match('/ascii/i', $this->_build_params['text_charset'])
1455
            && preg_match('/[^\x00-\x7F]/', $this->_txtbody)
1456
        ) {
1457
            $this->_build_params['text_encoding'] = 'quoted-printable';
1458
        }
1459
        // html body
1460
        if ($this->_build_params['html_encoding'] == '7bit'
1461
            && !preg_match('/ascii/i', $this->_build_params['html_charset'])
1462
            && preg_match('/[^\x00-\x7F]/', $this->_htmlbody)
1463
        ) {
1464
            $this->_build_params['html_encoding'] = 'quoted-printable';
1465
        }
1466
    }
1467
 
1468
} // End of class