web/lib/Zend/Mail/Transport/Abstract.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Mail
       
    17  * @subpackage Transport
       
    18  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    20  * @version    $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $
       
    21  */
       
    22 
       
    23 
       
    24 /**
       
    25  * @see Zend_Mime
       
    26  */
       
    27 require_once 'Zend/Mime.php';
       
    28 
       
    29 
       
    30 /**
       
    31  * Abstract for sending eMails through different
       
    32  * ways of transport
       
    33  *
       
    34  * @category   Zend
       
    35  * @package    Zend_Mail
       
    36  * @subpackage Transport
       
    37  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    38  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    39  */
       
    40 abstract class Zend_Mail_Transport_Abstract
       
    41 {
       
    42     /**
       
    43      * Mail body
       
    44      * @var string
       
    45      * @access public
       
    46      */
       
    47     public $body = '';
       
    48 
       
    49     /**
       
    50      * MIME boundary
       
    51      * @var string
       
    52      * @access public
       
    53      */
       
    54     public $boundary = '';
       
    55 
       
    56     /**
       
    57      * Mail header string
       
    58      * @var string
       
    59      * @access public
       
    60      */
       
    61     public $header = '';
       
    62 
       
    63     /**
       
    64      * Array of message headers
       
    65      * @var array
       
    66      * @access protected
       
    67      */
       
    68     protected $_headers = array();
       
    69 
       
    70     /**
       
    71      * Message is a multipart message
       
    72      * @var boolean
       
    73      * @access protected
       
    74      */
       
    75     protected $_isMultipart = false;
       
    76 
       
    77     /**
       
    78      * Zend_Mail object
       
    79      * @var false|Zend_Mail
       
    80      * @access protected
       
    81      */
       
    82     protected $_mail = false;
       
    83 
       
    84     /**
       
    85      * Array of message parts
       
    86      * @var array
       
    87      * @access protected
       
    88      */
       
    89     protected $_parts = array();
       
    90 
       
    91     /**
       
    92      * Recipients string
       
    93      * @var string
       
    94      * @access public
       
    95      */
       
    96     public $recipients = '';
       
    97 
       
    98     /**
       
    99      * EOL character string used by transport
       
   100      * @var string
       
   101      * @access public
       
   102      */
       
   103     public $EOL = "\r\n";
       
   104 
       
   105     /**
       
   106      * Send an email independent from the used transport
       
   107      *
       
   108      * The requisite information for the email will be found in the following
       
   109      * properties:
       
   110      *
       
   111      * - {@link $recipients} - list of recipients (string)
       
   112      * - {@link $header} - message header
       
   113      * - {@link $body} - message body
       
   114      */
       
   115     abstract protected function _sendMail();
       
   116 
       
   117     /**
       
   118      * Return all mail headers as an array
       
   119      *
       
   120      * If a boundary is given, a multipart header is generated with a
       
   121      * Content-Type of either multipart/alternative or multipart/mixed depending
       
   122      * on the mail parts present in the {@link $_mail Zend_Mail object} present.
       
   123      *
       
   124      * @param string $boundary
       
   125      * @return array
       
   126      */
       
   127     protected function _getHeaders($boundary)
       
   128     {
       
   129         if (null !== $boundary) {
       
   130             // Build multipart mail
       
   131             $type = $this->_mail->getType();
       
   132             if (!$type) {
       
   133                 if ($this->_mail->hasAttachments) {
       
   134                     $type = Zend_Mime::MULTIPART_MIXED;
       
   135                 } elseif ($this->_mail->getBodyText() && $this->_mail->getBodyHtml()) {
       
   136                     $type = Zend_Mime::MULTIPART_ALTERNATIVE;
       
   137                 } else {
       
   138                     $type = Zend_Mime::MULTIPART_MIXED;
       
   139                 }
       
   140             }
       
   141 
       
   142             $this->_headers['Content-Type'] = array(
       
   143                 $type . ';'
       
   144                 . $this->EOL
       
   145                 . " " . 'boundary="' . $boundary . '"'
       
   146             );
       
   147             $this->boundary = $boundary;
       
   148         }
       
   149 
       
   150         $this->_headers['MIME-Version'] = array('1.0');
       
   151 
       
   152         return $this->_headers;
       
   153     }
       
   154 
       
   155     /**
       
   156      * Prepend header name to header value
       
   157      *
       
   158      * @param string $item
       
   159      * @param string $key
       
   160      * @param string $prefix
       
   161      * @static
       
   162      * @access protected
       
   163      * @return void
       
   164      */
       
   165     protected static function _formatHeader(&$item, $key, $prefix)
       
   166     {
       
   167         $item = $prefix . ': ' . $item;
       
   168     }
       
   169 
       
   170     /**
       
   171      * Prepare header string for use in transport
       
   172      *
       
   173      * Prepares and generates {@link $header} based on the headers provided.
       
   174      *
       
   175      * @param mixed $headers
       
   176      * @access protected
       
   177      * @return void
       
   178      * @throws Zend_Mail_Transport_Exception if any header lines exceed 998
       
   179      * characters
       
   180      */
       
   181     protected function _prepareHeaders($headers)
       
   182     {
       
   183         if (!$this->_mail) {
       
   184             /**
       
   185              * @see Zend_Mail_Transport_Exception
       
   186              */
       
   187             require_once 'Zend/Mail/Transport/Exception.php';
       
   188             throw new Zend_Mail_Transport_Exception('Missing Zend_Mail object in _mail property');
       
   189         }
       
   190 
       
   191         $this->header = '';
       
   192 
       
   193         foreach ($headers as $header => $content) {
       
   194             if (isset($content['append'])) {
       
   195                 unset($content['append']);
       
   196                 $value = implode(',' . $this->EOL . ' ', $content);
       
   197                 $this->header .= $header . ': ' . $value . $this->EOL;
       
   198             } else {
       
   199                 array_walk($content, array(get_class($this), '_formatHeader'), $header);
       
   200                 $this->header .= implode($this->EOL, $content) . $this->EOL;
       
   201             }
       
   202         }
       
   203 
       
   204         // Sanity check on headers -- should not be > 998 characters
       
   205         $sane = true;
       
   206         foreach (explode($this->EOL, $this->header) as $line) {
       
   207             if (strlen(trim($line)) > 998) {
       
   208                 $sane = false;
       
   209                 break;
       
   210             }
       
   211         }
       
   212         if (!$sane) {
       
   213             /**
       
   214              * @see Zend_Mail_Transport_Exception
       
   215              */
       
   216             require_once 'Zend/Mail/Transport/Exception.php';
       
   217             throw new Zend_Mail_Exception('At least one mail header line is too long');
       
   218         }
       
   219     }
       
   220 
       
   221     /**
       
   222      * Generate MIME compliant message from the current configuration
       
   223      *
       
   224      * If both a text and HTML body are present, generates a
       
   225      * multipart/alternative Zend_Mime_Part containing the headers and contents
       
   226      * of each. Otherwise, uses whichever of the text or HTML parts present.
       
   227      *
       
   228      * The content part is then prepended to the list of Zend_Mime_Parts for
       
   229      * this message.
       
   230      *
       
   231      * @return void
       
   232      */
       
   233     protected function _buildBody()
       
   234     {
       
   235         if (($text = $this->_mail->getBodyText())
       
   236             && ($html = $this->_mail->getBodyHtml()))
       
   237         {
       
   238             // Generate unique boundary for multipart/alternative
       
   239             $mime = new Zend_Mime(null);
       
   240             $boundaryLine = $mime->boundaryLine($this->EOL);
       
   241             $boundaryEnd  = $mime->mimeEnd($this->EOL);
       
   242 
       
   243             $text->disposition = false;
       
   244             $html->disposition = false;
       
   245 
       
   246             $body = $boundaryLine
       
   247                   . $text->getHeaders($this->EOL)
       
   248                   . $this->EOL
       
   249                   . $text->getContent($this->EOL)
       
   250                   . $this->EOL
       
   251                   . $boundaryLine
       
   252                   . $html->getHeaders($this->EOL)
       
   253                   . $this->EOL
       
   254                   . $html->getContent($this->EOL)
       
   255                   . $this->EOL
       
   256                   . $boundaryEnd;
       
   257 
       
   258             $mp           = new Zend_Mime_Part($body);
       
   259             $mp->type     = Zend_Mime::MULTIPART_ALTERNATIVE;
       
   260             $mp->boundary = $mime->boundary();
       
   261 
       
   262             $this->_isMultipart = true;
       
   263 
       
   264             // Ensure first part contains text alternatives
       
   265             array_unshift($this->_parts, $mp);
       
   266 
       
   267             // Get headers
       
   268             $this->_headers = $this->_mail->getHeaders();
       
   269             return;
       
   270         }
       
   271 
       
   272         // If not multipart, then get the body
       
   273         if (false !== ($body = $this->_mail->getBodyHtml())) {
       
   274             array_unshift($this->_parts, $body);
       
   275         } elseif (false !== ($body = $this->_mail->getBodyText())) {
       
   276             array_unshift($this->_parts, $body);
       
   277         }
       
   278 
       
   279         if (!$body) {
       
   280             /**
       
   281              * @see Zend_Mail_Transport_Exception
       
   282              */
       
   283             require_once 'Zend/Mail/Transport/Exception.php';
       
   284             throw new Zend_Mail_Transport_Exception('No body specified');
       
   285         }
       
   286 
       
   287         // Get headers
       
   288         $this->_headers = $this->_mail->getHeaders();
       
   289         $headers = $body->getHeadersArray($this->EOL);
       
   290         foreach ($headers as $header) {
       
   291             // Headers in Zend_Mime_Part are kept as arrays with two elements, a
       
   292             // key and a value
       
   293             $this->_headers[$header[0]] = array($header[1]);
       
   294         }
       
   295     }
       
   296 
       
   297     /**
       
   298      * Send a mail using this transport
       
   299      *
       
   300      * @param  Zend_Mail $mail
       
   301      * @access public
       
   302      * @return void
       
   303      * @throws Zend_Mail_Transport_Exception if mail is empty
       
   304      */
       
   305     public function send(Zend_Mail $mail)
       
   306     {
       
   307         $this->_isMultipart = false;
       
   308         $this->_mail        = $mail;
       
   309         $this->_parts       = $mail->getParts();
       
   310         $mime               = $mail->getMime();
       
   311 
       
   312         // Build body content
       
   313         $this->_buildBody();
       
   314 
       
   315         // Determine number of parts and boundary
       
   316         $count    = count($this->_parts);
       
   317         $boundary = null;
       
   318         if ($count < 1) {
       
   319             /**
       
   320              * @see Zend_Mail_Transport_Exception
       
   321              */
       
   322             require_once 'Zend/Mail/Transport/Exception.php';
       
   323             throw new Zend_Mail_Transport_Exception('Empty mail cannot be sent');
       
   324         }
       
   325 
       
   326         if ($count > 1) {
       
   327             // Multipart message; create new MIME object and boundary
       
   328             $mime     = new Zend_Mime($this->_mail->getMimeBoundary());
       
   329             $boundary = $mime->boundary();
       
   330         } elseif ($this->_isMultipart) {
       
   331             // multipart/alternative -- grab boundary
       
   332             $boundary = $this->_parts[0]->boundary;
       
   333         }
       
   334 
       
   335         // Determine recipients, and prepare headers
       
   336         $this->recipients = implode(',', $mail->getRecipients());
       
   337         $this->_prepareHeaders($this->_getHeaders($boundary));
       
   338 
       
   339         // Create message body
       
   340         // This is done so that the same Zend_Mail object can be used in
       
   341         // multiple transports
       
   342         $message = new Zend_Mime_Message();
       
   343         $message->setParts($this->_parts);
       
   344         $message->setMime($mime);
       
   345         $this->body = $message->generateMessage($this->EOL);
       
   346 
       
   347         // Send to transport!
       
   348         $this->_sendMail();
       
   349     }
       
   350 }