Mail_Mime
[ class tree: Mail_Mime ] [ index: Mail_Mime ] [ all elements ]

Source for file mime.php

Documentation is available at mime.php

  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$
  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$valueeach($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 ($this->_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 ($this->_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 ($this->_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.      * @param array  $add_headers Additional part headers. Array keys can be in form
  391.      *                             of <header_name>:<parameter_name>
  392.      *
  393.      * @return mixed              True on success or PEAR_Error object
  394.      * @access public
  395.      */
  396.     function addAttachment($file,
  397.         $c_type      'application/octet-stream',
  398.         $name        '',
  399.         $isfile      = true,
  400.         $encoding    'base64',
  401.         $disposition 'attachment',
  402.         $charset     '',
  403.         $language    '',
  404.         $location    '',
  405.         $n_encoding  = null,
  406.         $f_encoding  = null,
  407.         $description '',
  408.         $h_charset   = null,
  409.         $add_headers = array()
  410.     {
  411.         $bodyfile = null;
  412.  
  413.         if ($isfile{
  414.             // Don't load file into memory
  415.             if ($this->_build_params['delay_file_io']{
  416.                 $filedata = null;
  417.                 $bodyfile $file;
  418.             else {
  419.                 if ($this->_isError($filedata $this->_file2str($file))) {
  420.                     return $filedata;
  421.                 }
  422.             }
  423.             // Force the name the user supplied, otherwise use $file
  424.             $filename ($name $name $this->_basename($file));
  425.         else {
  426.             $filedata $file;
  427.             $filename $name;
  428.         }
  429.  
  430.         if (!strlen($filename)) {
  431.             $msg "The supplied filename for the attachment can't be empty";
  432.             $err = PEAR::raiseError($msg);
  433.             return $err;
  434.         }
  435.  
  436.         $this->_parts[= array(
  437.             'body'        => $filedata,
  438.             'body_file'   => $bodyfile,
  439.             'name'        => $filename,
  440.             'c_type'      => $c_type,
  441.             'charset'     => $charset,
  442.             'encoding'    => $encoding,
  443.             'language'    => $language,
  444.             'location'    => $location,
  445.             'disposition' => $disposition,
  446.             'description' => $description,
  447.             'add_headers' => $add_headers,
  448.             'name_encoding'     => $n_encoding,
  449.             'filename_encoding' => $f_encoding,
  450.             'headers_charset'   => $h_charset,
  451.         );
  452.  
  453.         return true;
  454.     }
  455.  
  456.     /**
  457.      * Get the contents of the given file name as string
  458.      *
  459.      * @param string $file_name Path of file to process
  460.      *
  461.      * @return string           Contents of $file_name
  462.      * @access private
  463.      */
  464.     function _file2str($file_name)
  465.     {
  466.         // Check state of file and raise an error properly
  467.         if (!file_exists($file_name)) {
  468.             $err = PEAR::raiseError('File not found: ' $file_name);
  469.             return $err;
  470.         }
  471.         if (!is_file($file_name)) {
  472.             $err = PEAR::raiseError('Not a regular file: ' $file_name);
  473.             return $err;
  474.         }
  475.         if (!is_readable($file_name)) {
  476.             $err = PEAR::raiseError('File is not readable: ' $file_name);
  477.             return $err;
  478.         }
  479.  
  480.         // Temporarily reset magic_quotes_runtime and read file contents
  481.         if ($magic_quote_setting get_magic_quotes_runtime()) {
  482.             @ini_set('magic_quotes_runtime'0);
  483.         }
  484.         $cont file_get_contents($file_name);
  485.         if ($magic_quote_setting{
  486.             @ini_set('magic_quotes_runtime'$magic_quote_setting);
  487.         }
  488.  
  489.         return $cont;
  490.     }
  491.  
  492.     /**
  493.      * Adds a text subpart to the mimePart object and
  494.      * returns it during the build process.
  495.      *
  496.      * @param mixed  &$obj The object to add the part to, or
  497.      *                      null if a new object is to be created.
  498.      * @param string $text The text to add.
  499.      *
  500.      * @return object      The text mimePart object
  501.      * @access private
  502.      */
  503.     function _addTextPart(&$obj$text)
  504.     {
  505.         $params['content_type''text/plain';
  506.         $params['encoding']     $this->_build_params['text_encoding'];
  507.         $params['charset']      $this->_build_params['text_charset'];
  508.         $params['eol']          $this->_build_params['eol'];
  509.  
  510.         if (is_object($obj)) {
  511.             $ret $obj->addSubpart($text$params);
  512.             return $ret;
  513.         else {
  514.             $ret = new Mail_mimePart($text$params);
  515.             return $ret;
  516.         }
  517.     }
  518.  
  519.     /**
  520.      * Adds a html subpart to the mimePart object and
  521.      * returns it during the build process.
  522.      *
  523.      * @param mixed &$obj The object to add the part to, or
  524.      *                     null if a new object is to be created.
  525.      *
  526.      * @return object     The html mimePart object
  527.      * @access private
  528.      */
  529.     function _addHtmlPart(&$obj)
  530.     {
  531.         $params['content_type''text/html';
  532.         $params['encoding']     $this->_build_params['html_encoding'];
  533.         $params['charset']      $this->_build_params['html_charset'];
  534.         $params['eol']          $this->_build_params['eol'];
  535.  
  536.         if (is_object($obj)) {
  537.             $ret $obj->addSubpart($this->_htmlbody$params);
  538.             return $ret;
  539.         else {
  540.             $ret = new Mail_mimePart($this->_htmlbody$params);
  541.             return $ret;
  542.         }
  543.     }
  544.  
  545.     /**
  546.      * Creates a new mimePart object, using multipart/mixed as
  547.      * the initial content-type and returns it during the
  548.      * build process.
  549.      *
  550.      * @return object The multipart/mixed mimePart object
  551.      * @access private
  552.      */
  553.     function _addMixedPart()
  554.     {
  555.         $params                 = array();
  556.         $params['content_type''multipart/mixed';
  557.         $params['eol']          $this->_build_params['eol'];
  558.  
  559.         // Create empty multipart/mixed Mail_mimePart object to return
  560.         $ret = new Mail_mimePart(''$params);
  561.         return $ret;
  562.     }
  563.  
  564.     /**
  565.      * Adds a multipart/alternative part to a mimePart
  566.      * object (or creates one), and returns it during
  567.      * the build process.
  568.      *
  569.      * @param mixed &$obj The object to add the part to, or
  570.      *                     null if a new object is to be created.
  571.      *
  572.      * @return object     The multipart/mixed mimePart object
  573.      * @access private
  574.      */
  575.     function _addAlternativePart(&$obj)
  576.     {
  577.         $params['content_type''multipart/alternative';
  578.         $params['eol']          $this->_build_params['eol'];
  579.  
  580.         if (is_object($obj)) {
  581.             return $obj->addSubpart(''$params);
  582.         else {
  583.             $ret = new Mail_mimePart(''$params);
  584.             return $ret;
  585.         }
  586.     }
  587.  
  588.     /**
  589.      * Adds a multipart/related part to a mimePart
  590.      * object (or creates one), and returns it during
  591.      * the build process.
  592.      *
  593.      * @param mixed &$obj The object to add the part to, or
  594.      *                     null if a new object is to be created
  595.      *
  596.      * @return object     The multipart/mixed mimePart object
  597.      * @access private
  598.      */
  599.     function _addRelatedPart(&$obj)
  600.     {
  601.         $params['content_type''multipart/related';
  602.         $params['eol']          $this->_build_params['eol'];
  603.  
  604.         if (is_object($obj)) {
  605.             return $obj->addSubpart(''$params);
  606.         else {
  607.             $ret = new Mail_mimePart(''$params);
  608.             return $ret;
  609.         }
  610.     }
  611.  
  612.     /**
  613.      * Adds an html image subpart to a mimePart object
  614.      * and returns it during the build process.
  615.      *
  616.      * @param object &$obj  The mimePart to add the image to
  617.      * @param array  $value The image information
  618.      *
  619.      * @return object       The image mimePart object
  620.      * @access private
  621.      */
  622.     function _addHtmlImagePart(&$obj$value)
  623.     {
  624.         $params['content_type'$value['c_type'];
  625.         $params['encoding']     'base64';
  626.         $params['disposition']  'inline';
  627.         $params['filename']     $value['name'];
  628.         $params['cid']          $value['cid'];
  629.         $params['body_file']    $value['body_file'];
  630.         $params['eol']          $this->_build_params['eol'];
  631.  
  632.         if (!empty($value['name_encoding'])) {
  633.             $params['name_encoding'$value['name_encoding'];
  634.         }
  635.         if (!empty($value['filename_encoding'])) {
  636.             $params['filename_encoding'$value['filename_encoding'];
  637.         }
  638.  
  639.         $ret $obj->addSubpart($value['body']$params);
  640.         return $ret;
  641.     }
  642.  
  643.     /**
  644.      * Adds an attachment subpart to a mimePart object
  645.      * and returns it during the build process.
  646.      *
  647.      * @param object &$obj  The mimePart to add the image to
  648.      * @param array  $value The attachment information
  649.      *
  650.      * @return object       The image mimePart object
  651.      * @access private
  652.      */
  653.     function _addAttachmentPart(&$obj$value)
  654.     {
  655.         $params['eol']          $this->_build_params['eol'];
  656.         $params['filename']     $value['name'];
  657.         $params['encoding']     $value['encoding'];
  658.         $params['content_type'$value['c_type'];
  659.         $params['body_file']    $value['body_file'];
  660.         $params['disposition']  = isset($value['disposition']
  661.                                   $value['disposition''attachment';
  662.  
  663.         // content charset
  664.         if (!empty($value['charset'])) {
  665.             $params['charset'$value['charset'];
  666.         }
  667.         // headers charset (filename, description)
  668.         if (!empty($value['headers_charset'])) {
  669.             $params['headers_charset'$value['headers_charset'];
  670.         }
  671.         if (!empty($value['language'])) {
  672.             $params['language'$value['language'];
  673.         }
  674.         if (!empty($value['location'])) {
  675.             $params['location'$value['location'];
  676.         }
  677.         if (!empty($value['name_encoding'])) {
  678.             $params['name_encoding'$value['name_encoding'];
  679.         }
  680.         if (!empty($value['filename_encoding'])) {
  681.             $params['filename_encoding'$value['filename_encoding'];
  682.         }
  683.         if (!empty($value['description'])) {
  684.             $params['description'$value['description'];
  685.         }
  686.         if (is_array($value['add_headers'])) {
  687.             $params['headers'$value['add_headers'];
  688.         }
  689.  
  690.         $ret $obj->addSubpart($value['body']$params);
  691.         return $ret;
  692.     }
  693.  
  694.     /**
  695.      * Returns the complete e-mail, ready to send using an alternative
  696.      * mail delivery method. Note that only the mailpart that is made
  697.      * with Mail_Mime is created. This means that,
  698.      * YOU WILL HAVE NO TO: HEADERS UNLESS YOU SET IT YOURSELF
  699.      * using the $headers parameter!
  700.      * 
  701.      * @param string $separation The separation between these two parts.
  702.      * @param array  $params     The Build parameters passed to the
  703.      *                            &get() function. See &get for more info.
  704.      * @param array  $headers    The extra headers that should be passed
  705.      *                            to the &headers() function.
  706.      *                            See that function for more info.
  707.      * @param bool   $overwrite  Overwrite the existing headers with new.
  708.      *
  709.      * @return mixed The complete e-mail or PEAR error object
  710.      * @access public
  711.      */
  712.     function getMessage($separation = null$params = null$headers = null,
  713.         $overwrite = false
  714.     {
  715.         if ($separation === null{
  716.             $separation $this->_build_params['eol'];
  717.         }
  718.  
  719.         $body $this->get($params);
  720.  
  721.         if ($this->_isError($body)) {
  722.             return $body;
  723.         }
  724.  
  725.         $head $this->txtHeaders($headers$overwrite);
  726.         $mail $head $separation $body;
  727.         return $mail;
  728.     }
  729.  
  730.     /**
  731.      * Returns the complete e-mail body, ready to send using an alternative
  732.      * mail delivery method.
  733.      * 
  734.      * @param array $params The Build parameters passed to the
  735.      *                       &get() function. See &get for more info.
  736.      *
  737.      * @return mixed The e-mail body or PEAR error object
  738.      * @access public
  739.      * @since 1.6.0
  740.      */
  741.     function getMessageBody($params = null)
  742.     {
  743.         return $this->get($paramsnulltrue);
  744.     }
  745.  
  746.     /**
  747.      * Writes (appends) the complete e-mail into file.
  748.      * 
  749.      * @param string $filename  Output file location
  750.      * @param array  $params    The Build parameters passed to the
  751.      *                           &get() function. See &get for more info.
  752.      * @param array  $headers   The extra headers that should be passed
  753.      *                           to the &headers() function.
  754.      *                           See that function for more info.
  755.      * @param bool   $overwrite Overwrite the existing headers with new.
  756.      *
  757.      * @return mixed True or PEAR error object
  758.      * @access public
  759.      * @since 1.6.0
  760.      */
  761.     function saveMessage($filename$params = null$headers = null$overwrite = false)
  762.     {
  763.         // Check state of file and raise an error properly
  764.         if (file_exists($filename&& !is_writable($filename)) {
  765.             $err = PEAR::raiseError('File is not writable: ' $filename);
  766.             return $err;
  767.         }
  768.  
  769.         // Temporarily reset magic_quotes_runtime and read file contents
  770.         if ($magic_quote_setting get_magic_quotes_runtime()) {
  771.             @ini_set('magic_quotes_runtime'0);
  772.         }
  773.  
  774.         if (!($fh fopen($filename'ab'))) {
  775.             $err = PEAR::raiseError('Unable to open file: ' $filename);
  776.             return $err;
  777.         }
  778.  
  779.         // Write message headers into file (skipping Content-* headers)
  780.         $head $this->txtHeaders($headers$overwritetrue);
  781.         if (fwrite($fh$head=== false{
  782.             $err = PEAR::raiseError('Error writing to file: ' $filename);
  783.             return $err;
  784.         }
  785.  
  786.         fclose($fh);
  787.  
  788.         if ($magic_quote_setting{
  789.             @ini_set('magic_quotes_runtime'$magic_quote_setting);
  790.         }
  791.  
  792.         // Write the rest of the message into file
  793.         $res $this->get($params$filename);
  794.  
  795.         return $res $res : true;
  796.     }
  797.  
  798.     /**
  799.      * Writes (appends) the complete e-mail body into file.
  800.      * 
  801.      * @param string $filename Output file location
  802.      * @param array  $params   The Build parameters passed to the
  803.      *                          &get() function. See &get for more info.
  804.      *
  805.      * @return mixed True or PEAR error object
  806.      * @access public
  807.      * @since 1.6.0
  808.      */
  809.     function saveMessageBody($filename$params = null)
  810.     {
  811.         // Check state of file and raise an error properly
  812.         if (file_exists($filename&& !is_writable($filename)) {
  813.             $err = PEAR::raiseError('File is not writable: ' $filename);
  814.             return $err;
  815.         }
  816.  
  817.         // Temporarily reset magic_quotes_runtime and read file contents
  818.         if ($magic_quote_setting get_magic_quotes_runtime()) {
  819.             @ini_set('magic_quotes_runtime'0);
  820.         }
  821.  
  822.         if (!($fh fopen($filename'ab'))) {
  823.             $err = PEAR::raiseError('Unable to open file: ' $filename);
  824.             return $err;
  825.         }
  826.  
  827.         // Write the rest of the message into file
  828.         $res $this->get($params$filenametrue);
  829.  
  830.         return $res $res : true;
  831.     }
  832.  
  833.     /**
  834.      * Builds the multipart message from the list ($this->_parts) and
  835.      * returns the mime content.
  836.      *
  837.      * @param array    $params    Build parameters that change the way the email
  838.      *                             is built. Should be associative. See $_build_params.
  839.      * @param resource $filename  Output file where to save the message instead of
  840.      *                             returning it
  841.      * @param boolean  $skip_head True if you want to return/save only the message
  842.      *                             without headers
  843.      *
  844.      * @return mixed The MIME message content string, null or PEAR error object
  845.      * @access public
  846.      */
  847.     function &get($params = null$filename = null$skip_head = false)
  848.     {
  849.         if (isset($params)) {
  850.             while (list($key$valueeach($params)) {
  851.                 $this->_build_params[$key$value;
  852.             }
  853.         }
  854.  
  855.         if (isset($this->_headers['From'])) {
  856.             // Bug #11381: Illegal characters in domain ID
  857.             if (preg_match('#(@[0-9a-zA-Z\-\.]+)#'$this->_headers['From']$matches)) {
  858.                 $domainID $matches[1];
  859.             else {
  860.                 $domainID '@localhost';
  861.             }
  862.             foreach ($this->_html_images as $i => $img{
  863.                 $cid $this->_html_images[$i]['cid']
  864.                 if (!preg_match('#'.preg_quote($domainID).'$#'$cid)) {
  865.                     $this->_html_images[$i]['cid'$cid $domainID;
  866.                 }
  867.             }
  868.         }
  869.  
  870.         if (count($this->_html_images&& isset($this->_htmlbody)) {
  871.             foreach ($this->_html_images as $key => $value{
  872.                 $regex   = array();
  873.                 $regex['#(\s)((?i)src|background|href(?-i))\s*=\s*(["\']?)' .
  874.                             preg_quote($value['name']'#''\3#';
  875.                 $regex['#(?i)url(?-i)\(\s*(["\']?)' .
  876.                             preg_quote($value['name']'#''\1\s*\)#';
  877.  
  878.                 $rep   = array();
  879.                 $rep['\1\2=\3cid:' $value['cid'.'\3';
  880.                 $rep['url(\1cid:' $value['cid''\1)';
  881.  
  882.                 $this->_htmlbody preg_replace($regex$rep$this->_htmlbody);
  883.                 $this->_html_images[$key]['name']
  884.                     = $this->_basename($this->_html_images[$key]['name']);
  885.             }
  886.         }
  887.  
  888.         $this->_checkParams();
  889.  
  890.         $null        = null;
  891.         $attachments count($this->_parts)                 ? true : false;
  892.         $html_images count($this->_html_images)           ? true : false;
  893.         $html        strlen($this->_htmlbody)             ? true : false;
  894.         $text        (!$html && strlen($this->_txtbody))  ? true : false;
  895.  
  896.         switch (true{
  897.         case $text && !$attachments:
  898.             $message =$this->_addTextPart($null$this->_txtbody);
  899.             break;
  900.  
  901.         case !$text && !$html && $attachments:
  902.             $message =$this->_addMixedPart();
  903.             for ($i = 0; $i count($this->_parts)$i++{
  904.                 $this->_addAttachmentPart($message$this->_parts[$i]);
  905.             }
  906.             break;
  907.  
  908.         case $text && $attachments:
  909.             $message =$this->_addMixedPart();
  910.             $this->_addTextPart($message$this->_txtbody);
  911.             for ($i = 0; $i count($this->_parts)$i++{
  912.                 $this->_addAttachmentPart($message$this->_parts[$i]);
  913.             }
  914.             break;
  915.  
  916.         case $html && !$attachments && !$html_images:
  917.             if (isset($this->_txtbody)) {
  918.                 $message =$this->_addAlternativePart($null);
  919.                 $this->_addTextPart($message$this->_txtbody);
  920.                 $this->_addHtmlPart($message);
  921.             else {
  922.                 $message =$this->_addHtmlPart($null);
  923.             }
  924.             break;
  925.  
  926.         case $html && !$attachments && $html_images:
  927.             // * Content-Type: multipart/alternative;
  928.             //    * text
  929.             //    * Content-Type: multipart/related;
  930.             //       * html
  931.             //       * image...
  932.             if (isset($this->_txtbody)) {
  933.                 $message =$this->_addAlternativePart($null);
  934.                 $this->_addTextPart($message$this->_txtbody);
  935.  
  936.                 $ht =$this->_addRelatedPart($message);
  937.                 $this->_addHtmlPart($ht);
  938.                 for ($i = 0; $i count($this->_html_images)$i++{
  939.                     $this->_addHtmlImagePart($ht$this->_html_images[$i]);
  940.                 }
  941.             else {
  942.                 // * Content-Type: multipart/related;
  943.                 //    * html
  944.                 //    * image...
  945.                 $message =$this->_addRelatedPart($null);
  946.                 $this->_addHtmlPart($message);
  947.                 for ($i = 0; $i count($this->_html_images)$i++{
  948.                     $this->_addHtmlImagePart($message$this->_html_images[$i]);
  949.                 }
  950.             }
  951.             /*
  952.             // #13444, #9725: the code below was a non-RFC compliant hack
  953.             // * Content-Type: multipart/related;
  954.             //    * Content-Type: multipart/alternative;
  955.             //        * text
  956.             //        * html
  957.             //    * image...
  958.             $message =& $this->_addRelatedPart($null);
  959.             if (isset($this->_txtbody)) {
  960.                 $alt =& $this->_addAlternativePart($message);
  961.                 $this->_addTextPart($alt, $this->_txtbody);
  962.                 $this->_addHtmlPart($alt);
  963.             } else {
  964.                 $this->_addHtmlPart($message);
  965.             }
  966.             for ($i = 0; $i < count($this->_html_images); $i++) {
  967.                 $this->_addHtmlImagePart($message, $this->_html_images[$i]);
  968.             }
  969.             */
  970.             break;
  971.  
  972.         case $html && $attachments && !$html_images:
  973.             $message =$this->_addMixedPart();
  974.             if (isset($this->_txtbody)) {
  975.                 $alt =$this->_addAlternativePart($message);
  976.                 $this->_addTextPart($alt$this->_txtbody);
  977.                 $this->_addHtmlPart($alt);
  978.             else {
  979.                 $this->_addHtmlPart($message);
  980.             }
  981.             for ($i = 0; $i count($this->_parts)$i++{
  982.                 $this->_addAttachmentPart($message$this->_parts[$i]);
  983.             }
  984.             break;
  985.  
  986.         case $html && $attachments && $html_images:
  987.             $message =$this->_addMixedPart();
  988.             if (isset($this->_txtbody)) {
  989.                 $alt =$this->_addAlternativePart($message);
  990.                 $this->_addTextPart($alt$this->_txtbody);
  991.                 $rel =$this->_addRelatedPart($alt);
  992.             else {
  993.                 $rel =$this->_addRelatedPart($message);
  994.             }
  995.             $this->_addHtmlPart($rel);
  996.             for ($i = 0; $i count($this->_html_images)$i++{
  997.                 $this->_addHtmlImagePart($rel$this->_html_images[$i]);
  998.             }
  999.             for ($i = 0; $i count($this->_parts)$i++{
  1000.                 $this->_addAttachmentPart($message$this->_parts[$i]);
  1001.             }
  1002.             break;
  1003.  
  1004.         }
  1005.  
  1006.         if (!isset($message)) {
  1007.             $ret = null;
  1008.             return $ret;
  1009.         }
  1010.  
  1011.         // Use saved boundary
  1012.         if (!empty($this->_build_params['boundary'])) {
  1013.             $boundary $this->_build_params['boundary'];
  1014.         else {
  1015.             $boundary = null;
  1016.         }
  1017.  
  1018.         // Write output to file
  1019.         if ($filename{
  1020.             // Append mimePart message headers and body into file
  1021.             $headers $message->encodeToFile($filename$boundary$skip_head);
  1022.             if ($this->_isError($headers)) {
  1023.                 return $headers;
  1024.             }
  1025.             $this->_headers array_merge($this->_headers$headers);
  1026.             $ret = null;
  1027.             return $ret;
  1028.         else {
  1029.             $output $message->encode($boundary$skip_head);
  1030.             if ($this->_isError($output)) {
  1031.                 return $output;
  1032.             }
  1033.             $this->_headers array_merge($this->_headers$output['headers']);
  1034.             $body $output['body'];
  1035.             return $body;
  1036.         }
  1037.     }
  1038.  
  1039.     /**
  1040.      * Returns an array with the headers needed to prepend to the email
  1041.      * (MIME-Version and Content-Type). Format of argument is:
  1042.      * $array['header-name'] = 'header-value';
  1043.      *
  1044.      * @param array $xtra_headers Assoc array with any extra headers (optional)
  1045.      *                             (Don't set Content-Type for multipart messages here!)
  1046.      * @param bool  $overwrite    Overwrite already existing headers.
  1047.      * @param bool  $skip_content Don't return content headers: Content-Type,
  1048.      *                             Content-Disposition and Content-Transfer-Encoding
  1049.      * 
  1050.      * @return array              Assoc array with the mime headers
  1051.      * @access public
  1052.      */
  1053.     function &headers($xtra_headers = null$overwrite = false$skip_content = false)
  1054.     {
  1055.         // Add mime version header
  1056.         $headers['MIME-Version''1.0';
  1057.  
  1058.         // Content-Type and Content-Transfer-Encoding headers should already
  1059.         // be present if get() was called, but we'll re-set them to make sure
  1060.         // we got them when called before get() or something in the message
  1061.         // has been changed after get() [#14780]
  1062.         if (!$skip_content{
  1063.             $headers += $this->_contentHeaders();
  1064.         }
  1065.  
  1066.         if (!empty($xtra_headers)) {
  1067.             $headers array_merge($headers$xtra_headers);
  1068.         }
  1069.  
  1070.         if ($overwrite{
  1071.             $this->_headers array_merge($this->_headers$headers);
  1072.         else {
  1073.             $this->_headers array_merge($headers$this->_headers);
  1074.         }
  1075.  
  1076.         $headers $this->_headers;
  1077.  
  1078.         if ($skip_content{
  1079.             unset($headers['Content-Type']);
  1080.             unset($headers['Content-Transfer-Encoding']);
  1081.             unset($headers['Content-Disposition']);
  1082.         else if (!empty($this->_build_params['ctype'])) {
  1083.             $headers['Content-Type'$this->_build_params['ctype'];
  1084.         }
  1085.  
  1086.         $encodedHeaders $this->_encodeHeaders($headers);
  1087.         return $encodedHeaders;
  1088.     }
  1089.  
  1090.     /**
  1091.      * Get the text version of the headers
  1092.      * (usefull if you want to use the PHP mail() function)
  1093.      *
  1094.      * @param array $xtra_headers Assoc array with any extra headers (optional)
  1095.      *                             (Don't set Content-Type for multipart messages here!)
  1096.      * @param bool  $overwrite    Overwrite the existing headers with new.
  1097.      * @param bool  $skip_content Don't return content headers: Content-Type,
  1098.      *                             Content-Disposition and Content-Transfer-Encoding
  1099.      *
  1100.      * @return string             Plain text headers
  1101.      * @access public
  1102.      */
  1103.     function txtHeaders($xtra_headers = null$overwrite = false$skip_content = false)
  1104.     {
  1105.         $headers $this->headers($xtra_headers$overwrite$skip_content);
  1106.  
  1107.         // Place Received: headers at the beginning of the message
  1108.         // Spam detectors often flag messages with it after the Subject: as spam
  1109.         if (isset($headers['Received'])) {
  1110.             $received $headers['Received'];
  1111.             unset($headers['Received']);
  1112.             $headers = array('Received' => $received$headers;
  1113.         }
  1114.  
  1115.         $ret '';
  1116.         $eol $this->_build_params['eol'];
  1117.  
  1118.         foreach ($headers as $key => $val{
  1119.             if (is_array($val)) {
  1120.                 foreach ($val as $value{
  1121.                     $ret .= "$key$value" . $eol;
  1122.                 }
  1123.             else {
  1124.                 $ret .= "$key$val" . $eol;
  1125.             }
  1126.         }
  1127.  
  1128.         return $ret;
  1129.     }
  1130.  
  1131.     /**
  1132.      * Sets message Content-Type header.
  1133.      * Use it to build messages with various content-types e.g. miltipart/raport
  1134.      * not supported by _contentHeaders() function.
  1135.      *
  1136.      * @param string $type   Type name
  1137.      * @param array  $params Hash array of header parameters
  1138.      *
  1139.      * @return void 
  1140.      * @access public
  1141.      * @since 1.7.0
  1142.      */
  1143.     function setContentType($type$params = array())
  1144.     {
  1145.         $header $type;
  1146.  
  1147.         $eol !empty($this->_build_params['eol'])
  1148.             ? $this->_build_params['eol'"\r\n";
  1149.  
  1150.         // add parameters
  1151.         $token_regexp '#([^\x21\x23-\x27\x2A\x2B\x2D'
  1152.             . '\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#';
  1153.         if (is_array($params)) {
  1154.             foreach ($params as $name => $value{
  1155.                 if ($name == 'boundary'{
  1156.                     $this->_build_params['boundary'$value;
  1157.                 }
  1158.                 if (!preg_match($token_regexp$value)) {
  1159.                     $header .= ";$eol $name=$value";
  1160.                 else {
  1161.                     $value addcslashes($value'\\"');
  1162.                     $header .= ";$eol $name=\"$value\"";
  1163.                 }
  1164.             }
  1165.         }
  1166.  
  1167.         // add required boundary parameter if not defined
  1168.         if (preg_match('/^multipart\//i'$type)) {
  1169.             if (empty($this->_build_params['boundary'])) {
  1170.                 $this->_build_params['boundary''=_' md5(rand(microtime());
  1171.             }
  1172.  
  1173.             $header .= ";$eol boundary=\"".$this->_build_params['boundary']."\"";
  1174.         }
  1175.  
  1176.         $this->_build_params['ctype'$header;
  1177.     }
  1178.  
  1179.     /**
  1180.      * Sets the Subject header
  1181.      *
  1182.      * @param string $subject String to set the subject to.
  1183.      *
  1184.      * @return void 
  1185.      * @access public
  1186.      */
  1187.     function setSubject($subject)
  1188.     {
  1189.         $this->_headers['Subject'$subject;
  1190.     }
  1191.  
  1192.     /**
  1193.      * Set an email to the From (the sender) header
  1194.      *
  1195.      * @param string $email The email address to use
  1196.      *
  1197.      * @return void 
  1198.      * @access public
  1199.      */
  1200.     function setFrom($email)
  1201.     {
  1202.         $this->_headers['From'$email;
  1203.     }
  1204.  
  1205.     /**
  1206.      * Add an email to the To header
  1207.      * (multiple calls to this method are allowed)
  1208.      *
  1209.      * @param string $email The email direction to add
  1210.      *
  1211.      * @return void 
  1212.      * @access public
  1213.      */
  1214.     function addTo($email)
  1215.     {
  1216.         if (isset($this->_headers['To'])) {
  1217.             $this->_headers['To'.= "$email";
  1218.         else {
  1219.             $this->_headers['To'$email;
  1220.         }
  1221.     }
  1222.  
  1223.     /**
  1224.      * Add an email to the Cc (carbon copy) header
  1225.      * (multiple calls to this method are allowed)
  1226.      *
  1227.      * @param string $email The email direction to add
  1228.      *
  1229.      * @return void 
  1230.      * @access public
  1231.      */
  1232.     function addCc($email)
  1233.     {
  1234.         if (isset($this->_headers['Cc'])) {
  1235.             $this->_headers['Cc'.= "$email";
  1236.         else {
  1237.             $this->_headers['Cc'$email;
  1238.         }
  1239.     }
  1240.  
  1241.     /**
  1242.      * Add an email to the Bcc (blank carbon copy) header
  1243.      * (multiple calls to this method are allowed)
  1244.      *
  1245.      * @param string $email The email direction to add
  1246.      *
  1247.      * @return void 
  1248.      * @access public
  1249.      */
  1250.     function addBcc($email)
  1251.     {
  1252.         if (isset($this->_headers['Bcc'])) {
  1253.             $this->_headers['Bcc'.= "$email";
  1254.         else {
  1255.             $this->_headers['Bcc'$email;
  1256.         }
  1257.     }
  1258.  
  1259.     /**
  1260.      * Since the PHP send function requires you to specify
  1261.      * recipients (To: header) separately from the other
  1262.      * headers, the To: header is not properly encoded.
  1263.      * To fix this, you can use this public method to
  1264.      * encode your recipients before sending to the send
  1265.      * function
  1266.      *
  1267.      * @param string $recipients A comma-delimited list of recipients
  1268.      *
  1269.      * @return string            Encoded data
  1270.      * @access public
  1271.      */
  1272.     function encodeRecipients($recipients)
  1273.     {
  1274.         $input = array("To" => $recipients);
  1275.         $retval $this->_encodeHeaders($input);
  1276.         return $retval["To";
  1277.     }
  1278.  
  1279.     /**
  1280.      * Encodes headers as per RFC2047
  1281.      *
  1282.      * @param array $input  The header data to encode
  1283.      * @param array $params Extra build parameters
  1284.      *
  1285.      * @return array        Encoded data
  1286.      * @access private
  1287.      */
  1288.     function _encodeHeaders($input$params = array())
  1289.     {
  1290.         $build_params $this->_build_params;
  1291.         while (list($key$valueeach($params)) {
  1292.             $build_params[$key$value;
  1293.         }
  1294.  
  1295.         foreach ($input as $hdr_name => $hdr_value{
  1296.             if (is_array($hdr_value)) {
  1297.                 foreach ($hdr_value as $idx => $value{
  1298.                     $input[$hdr_name][$idx$this->encodeHeader(
  1299.                         $hdr_name$value,
  1300.                         $build_params['head_charset']$build_params['head_encoding']
  1301.                     );
  1302.                 }
  1303.             else {
  1304.                 $input[$hdr_name$this->encodeHeader(
  1305.                     $hdr_name$hdr_value,
  1306.                     $build_params['head_charset']$build_params['head_encoding']
  1307.                 );
  1308.             }
  1309.         }
  1310.  
  1311.         return $input;
  1312.     }
  1313.  
  1314.     /**
  1315.      * Encodes a header as per RFC2047
  1316.      *
  1317.      * @param string $name     The header name
  1318.      * @param string $value    The header data to encode
  1319.      * @param string $charset  Character set name
  1320.      * @param string $encoding Encoding name (base64 or quoted-printable)
  1321.      *
  1322.      * @return string          Encoded header data (without a name)
  1323.      * @access public
  1324.      * @since 1.5.3
  1325.      */
  1326.     function encodeHeader($name$value$charset$encoding)
  1327.     {
  1328.         $mime_part = new Mail_mimePart;
  1329.         return $mime_part->encodeHeader(
  1330.             $name$value$charset$encoding$this->_build_params['eol']
  1331.         );
  1332.     }
  1333.  
  1334.     /**
  1335.      * Get file's basename (locale independent)
  1336.      *
  1337.      * @param string $filename Filename
  1338.      *
  1339.      * @return string          Basename
  1340.      * @access private
  1341.      */
  1342.     function _basename($filename)
  1343.     {
  1344.         // basename() is not unicode safe and locale dependent
  1345.         if (stristr(PHP_OS'win'|| stristr(PHP_OS'netware')) {
  1346.             return preg_replace('/^.*[\\\\\\/]/'''$filename);
  1347.         else {
  1348.             return preg_replace('/^.*[\/]/'''$filename);
  1349.         }
  1350.     }
  1351.  
  1352.     /**
  1353.      * Get Content-Type and Content-Transfer-Encoding headers of the message
  1354.      *
  1355.      * @return array Headers array
  1356.      * @access private
  1357.      */
  1358.     function _contentHeaders()
  1359.     {
  1360.         $attachments count($this->_parts)                 ? true : false;
  1361.         $html_images count($this->_html_images)           ? true : false;
  1362.         $html        strlen($this->_htmlbody)             ? true : false;
  1363.         $text        (!$html && strlen($this->_txtbody))  ? true : false;
  1364.         $headers     = array();
  1365.  
  1366.         // See get()
  1367.         switch (true{
  1368.         case $text && !$attachments:
  1369.             $headers['Content-Type''text/plain';
  1370.             break;
  1371.  
  1372.         case !$text && !$html && $attachments:
  1373.         case $text && $attachments:
  1374.         case $html && $attachments && !$html_images:
  1375.         case $html && $attachments && $html_images:
  1376.             $headers['Content-Type''multipart/mixed';
  1377.             break;
  1378.  
  1379.         case $html && !$attachments && !$html_images && isset($this->_txtbody):
  1380.         case $html && !$attachments && $html_images && isset($this->_txtbody):
  1381.             $headers['Content-Type''multipart/alternative';
  1382.             break;
  1383.  
  1384.         case $html && !$attachments && !$html_images && !isset($this->_txtbody):
  1385.             $headers['Content-Type''text/html';
  1386.             break;
  1387.  
  1388.         case $html && !$attachments && $html_images && !isset($this->_txtbody):
  1389.             $headers['Content-Type''multipart/related';
  1390.             break;
  1391.  
  1392.         default:
  1393.             return $headers;
  1394.         }
  1395.  
  1396.         $this->_checkParams();
  1397.  
  1398.         $eol !empty($this->_build_params['eol'])
  1399.             ? $this->_build_params['eol'"\r\n";
  1400.  
  1401.         if ($headers['Content-Type'== 'text/plain'{
  1402.             // single-part message: add charset and encoding
  1403.             $charset 'charset=' $this->_build_params['text_charset'];
  1404.             // place charset parameter in the same line, if possible
  1405.             // 26 = strlen("Content-Type: text/plain; ")
  1406.             $headers['Content-Type']
  1407.                 .= (strlen($charset+ 26 <= 76? "$charset" : ";$eol $charset";
  1408.             $headers['Content-Transfer-Encoding']
  1409.                 = $this->_build_params['text_encoding'];
  1410.         else if ($headers['Content-Type'== 'text/html'{
  1411.             // single-part message: add charset and encoding
  1412.             $charset 'charset=' $this->_build_params['html_charset'];
  1413.             // place charset parameter in the same line, if possible
  1414.             $headers['Content-Type']
  1415.                 .= (strlen($charset+ 25 <= 76? "$charset" : ";$eol $charset";
  1416.             $headers['Content-Transfer-Encoding']
  1417.                 = $this->_build_params['html_encoding'];
  1418.         else {
  1419.             // multipart message: and boundary
  1420.             if (!empty($this->_build_params['boundary'])) {
  1421.                 $boundary $this->_build_params['boundary'];
  1422.             else if (!empty($this->_headers['Content-Type'])
  1423.                 && preg_match('/boundary="([^"]+)"/'$this->_headers['Content-Type']$m)
  1424.             {
  1425.                 $boundary $m[1];
  1426.             else {
  1427.                 $boundary '=_' md5(rand(microtime());
  1428.             }
  1429.  
  1430.             $this->_build_params['boundary'$boundary;
  1431.             $headers['Content-Type'.= ";$eol boundary=\"$boundary\"";
  1432.         }
  1433.  
  1434.         return $headers;
  1435.     }
  1436.  
  1437.     /**
  1438.      * Validate and set build parameters
  1439.      *
  1440.      * @return void 
  1441.      * @access private
  1442.      */
  1443.     function _checkParams()
  1444.     {
  1445.         $encodings = array('7bit''8bit''base64''quoted-printable');
  1446.  
  1447.         $this->_build_params['text_encoding']
  1448.             = strtolower($this->_build_params['text_encoding']);
  1449.         $this->_build_params['html_encoding']
  1450.             = strtolower($this->_build_params['html_encoding']);
  1451.  
  1452.         if (!in_array($this->_build_params['text_encoding']$encodings)) {
  1453.             $this->_build_params['text_encoding''7bit';
  1454.         }
  1455.         if (!in_array($this->_build_params['html_encoding']$encodings)) {
  1456.             $this->_build_params['html_encoding''7bit';
  1457.         }
  1458.  
  1459.         // text body
  1460.         if ($this->_build_params['text_encoding'== '7bit'
  1461.             && !preg_match('/ascii/i'$this->_build_params['text_charset'])
  1462.             && preg_match('/[^\x00-\x7F]/'$this->_txtbody)
  1463.         {
  1464.             $this->_build_params['text_encoding''quoted-printable';
  1465.         }
  1466.         // html body
  1467.         if ($this->_build_params['html_encoding'== '7bit'
  1468.             && !preg_match('/ascii/i'$this->_build_params['html_charset'])
  1469.             && preg_match('/[^\x00-\x7F]/'$this->_htmlbody)
  1470.         {
  1471.             $this->_build_params['html_encoding''quoted-printable';
  1472.         }
  1473.     }
  1474.  
  1475.     /**
  1476.      * PEAR::isError wrapper
  1477.      *
  1478.      * @param mixed $data Object
  1479.      *
  1480.      * @return bool True if object is an instance of PEAR_Error
  1481.      * @access private
  1482.      */
  1483.     function _isError($data)
  1484.     {
  1485.         // PEAR::isError() is not PHP 5.4 compatible (see Bug #19473)
  1486.         if (is_object($data&& is_a($data'PEAR_Error')) {
  1487.             return true;
  1488.         }
  1489.  
  1490.         return false;
  1491.     }
  1492.  
  1493. // End of class

Documentation generated on Tue, 25 Dec 2012 17:30:04 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.