File indexing completed on 2024-12-22 05:36:51
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Mail 0017 * @subpackage Transport 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 0024 /** 0025 * @see Zend_Mime 0026 */ 0027 // require_once 'Zend/Mime.php'; 0028 0029 0030 /** 0031 * Abstract for sending eMails through different 0032 * ways of transport 0033 * 0034 * @category Zend 0035 * @package Zend_Mail 0036 * @subpackage Transport 0037 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0038 * @license http://framework.zend.com/license/new-bsd New BSD License 0039 */ 0040 abstract class Zend_Mail_Transport_Abstract 0041 { 0042 /** 0043 * Mail body 0044 * @var string 0045 * @access public 0046 */ 0047 public $body = ''; 0048 0049 /** 0050 * MIME boundary 0051 * @var string 0052 * @access public 0053 */ 0054 public $boundary = ''; 0055 0056 /** 0057 * Mail header string 0058 * @var string 0059 * @access public 0060 */ 0061 public $header = ''; 0062 0063 /** 0064 * Array of message headers 0065 * @var array 0066 * @access protected 0067 */ 0068 protected $_headers = array(); 0069 0070 /** 0071 * Message is a multipart message 0072 * @var boolean 0073 * @access protected 0074 */ 0075 protected $_isMultipart = false; 0076 0077 /** 0078 * Zend_Mail object 0079 * @var false|Zend_Mail 0080 * @access protected 0081 */ 0082 protected $_mail = false; 0083 0084 /** 0085 * Array of message parts 0086 * @var array 0087 * @access protected 0088 */ 0089 protected $_parts = array(); 0090 0091 /** 0092 * Recipients string 0093 * @var string 0094 * @access public 0095 */ 0096 public $recipients = ''; 0097 0098 /** 0099 * EOL character string used by transport 0100 * @var string 0101 * @access public 0102 */ 0103 public $EOL = "\r\n"; 0104 0105 /** 0106 * Send an email independent from the used transport 0107 * 0108 * The requisite information for the email will be found in the following 0109 * properties: 0110 * 0111 * - {@link $recipients} - list of recipients (string) 0112 * - {@link $header} - message header 0113 * - {@link $body} - message body 0114 */ 0115 abstract protected function _sendMail(); 0116 0117 /** 0118 * Return all mail headers as an array 0119 * 0120 * If a boundary is given, a multipart header is generated with a 0121 * Content-Type of either multipart/alternative or multipart/mixed depending 0122 * on the mail parts present in the {@link $_mail Zend_Mail object} present. 0123 * 0124 * @param string $boundary 0125 * @return array 0126 */ 0127 protected function _getHeaders($boundary) 0128 { 0129 if (null !== $boundary) { 0130 // Build multipart mail 0131 $type = $this->_mail->getType(); 0132 if (!$type) { 0133 if ($this->_mail->hasAttachments) { 0134 $type = Zend_Mime::MULTIPART_MIXED; 0135 } elseif ($this->_mail->getBodyText() && $this->_mail->getBodyHtml()) { 0136 $type = Zend_Mime::MULTIPART_ALTERNATIVE; 0137 } else { 0138 $type = Zend_Mime::MULTIPART_MIXED; 0139 } 0140 } 0141 0142 $this->_headers['Content-Type'] = array( 0143 $type . ';' 0144 . $this->EOL 0145 . " " . 'boundary="' . $boundary . '"' 0146 ); 0147 $this->boundary = $boundary; 0148 } 0149 0150 $this->_headers['MIME-Version'] = array('1.0'); 0151 0152 return $this->_headers; 0153 } 0154 0155 /** 0156 * Prepend header name to header value 0157 * 0158 * @param string $item 0159 * @param string $key 0160 * @param string $prefix 0161 * @static 0162 * @access protected 0163 * @return void 0164 */ 0165 protected static function _formatHeader(&$item, $key, $prefix) 0166 { 0167 $item = $prefix . ': ' . $item; 0168 } 0169 0170 /** 0171 * Prepare header string for use in transport 0172 * 0173 * Prepares and generates {@link $header} based on the headers provided. 0174 * 0175 * @param mixed $headers 0176 * @access protected 0177 * @return void 0178 * @throws Zend_Mail_Transport_Exception if any header lines exceed 998 0179 * characters 0180 */ 0181 protected function _prepareHeaders($headers) 0182 { 0183 if (!$this->_mail) { 0184 /** 0185 * @see Zend_Mail_Transport_Exception 0186 */ 0187 // require_once 'Zend/Mail/Transport/Exception.php'; 0188 throw new Zend_Mail_Transport_Exception('Missing Zend_Mail object in _mail property'); 0189 } 0190 0191 $this->header = ''; 0192 0193 foreach ($headers as $header => $content) { 0194 if (isset($content['append'])) { 0195 unset($content['append']); 0196 $value = implode(',' . $this->EOL . ' ', $content); 0197 $this->header .= $header . ': ' . $value . $this->EOL; 0198 } else { 0199 array_walk($content, array(get_class($this), '_formatHeader'), $header); 0200 $this->header .= implode($this->EOL, $content) . $this->EOL; 0201 } 0202 } 0203 0204 // Sanity check on headers -- should not be > 998 characters 0205 $sane = true; 0206 foreach (explode($this->EOL, $this->header) as $line) { 0207 if (strlen(trim($line)) > 998) { 0208 $sane = false; 0209 break; 0210 } 0211 } 0212 if (!$sane) { 0213 /** 0214 * @see Zend_Mail_Transport_Exception 0215 */ 0216 // require_once 'Zend/Mail/Transport/Exception.php'; 0217 throw new Zend_Mail_Exception('At least one mail header line is too long'); 0218 } 0219 } 0220 0221 /** 0222 * Generate MIME compliant message from the current configuration 0223 * 0224 * If both a text and HTML body are present, generates a 0225 * multipart/alternative Zend_Mime_Part containing the headers and contents 0226 * of each. Otherwise, uses whichever of the text or HTML parts present. 0227 * 0228 * The content part is then prepended to the list of Zend_Mime_Parts for 0229 * this message. 0230 * 0231 * @return void 0232 */ 0233 protected function _buildBody() 0234 { 0235 if (($text = $this->_mail->getBodyText()) 0236 && ($html = $this->_mail->getBodyHtml())) 0237 { 0238 // Generate unique boundary for multipart/alternative 0239 $mime = new Zend_Mime(null); 0240 $boundaryLine = $mime->boundaryLine($this->EOL); 0241 $boundaryEnd = $mime->mimeEnd($this->EOL); 0242 0243 $text->disposition = false; 0244 $html->disposition = false; 0245 0246 $body = $boundaryLine 0247 . $text->getHeaders($this->EOL) 0248 . $this->EOL 0249 . $text->getContent($this->EOL) 0250 . $this->EOL 0251 . $boundaryLine 0252 . $html->getHeaders($this->EOL) 0253 . $this->EOL 0254 . $html->getContent($this->EOL) 0255 . $this->EOL 0256 . $boundaryEnd; 0257 0258 $mp = new Zend_Mime_Part($body); 0259 $mp->type = Zend_Mime::MULTIPART_ALTERNATIVE; 0260 $mp->boundary = $mime->boundary(); 0261 0262 $this->_isMultipart = true; 0263 0264 // Ensure first part contains text alternatives 0265 array_unshift($this->_parts, $mp); 0266 0267 // Get headers 0268 $this->_headers = $this->_mail->getHeaders(); 0269 return; 0270 } 0271 0272 // If not multipart, then get the body 0273 if (false !== ($body = $this->_mail->getBodyHtml())) { 0274 array_unshift($this->_parts, $body); 0275 } elseif (false !== ($body = $this->_mail->getBodyText())) { 0276 array_unshift($this->_parts, $body); 0277 } 0278 0279 if (!$body) { 0280 /** 0281 * @see Zend_Mail_Transport_Exception 0282 */ 0283 // require_once 'Zend/Mail/Transport/Exception.php'; 0284 throw new Zend_Mail_Transport_Exception('No body specified'); 0285 } 0286 0287 // Get headers 0288 $this->_headers = $this->_mail->getHeaders(); 0289 $headers = $body->getHeadersArray($this->EOL); 0290 foreach ($headers as $header) { 0291 // Headers in Zend_Mime_Part are kept as arrays with two elements, a 0292 // key and a value 0293 $this->_headers[$header[0]] = array($header[1]); 0294 } 0295 } 0296 0297 /** 0298 * Send a mail using this transport 0299 * 0300 * @param Zend_Mail $mail 0301 * @access public 0302 * @return void 0303 * @throws Zend_Mail_Transport_Exception if mail is empty 0304 */ 0305 public function send(Zend_Mail $mail) 0306 { 0307 $this->_isMultipart = false; 0308 $this->_mail = $mail; 0309 $this->_parts = $mail->getParts(); 0310 $mime = $mail->getMime(); 0311 0312 // Build body content 0313 $this->_buildBody(); 0314 0315 // Determine number of parts and boundary 0316 $count = count($this->_parts); 0317 $boundary = null; 0318 if ($count < 1) { 0319 /** 0320 * @see Zend_Mail_Transport_Exception 0321 */ 0322 // require_once 'Zend/Mail/Transport/Exception.php'; 0323 throw new Zend_Mail_Transport_Exception('Empty mail cannot be sent'); 0324 } 0325 0326 if ($count > 1) { 0327 // Multipart message; create new MIME object and boundary 0328 $mime = new Zend_Mime($this->_mail->getMimeBoundary()); 0329 $boundary = $mime->boundary(); 0330 } elseif ($this->_isMultipart) { 0331 // multipart/alternative -- grab boundary 0332 $boundary = $this->_parts[0]->boundary; 0333 } 0334 0335 // Determine recipients, and prepare headers 0336 $this->recipients = implode(',', $mail->getRecipients()); 0337 $this->_prepareHeaders($this->_getHeaders($boundary)); 0338 0339 // Create message body 0340 // This is done so that the same Zend_Mail object can be used in 0341 // multiple transports 0342 $message = new Zend_Mime_Message(); 0343 $message->setParts($this->_parts); 0344 $message->setMime($mime); 0345 $this->body = $message->generateMessage($this->EOL); 0346 0347 // Send to transport! 0348 $this->_sendMail(); 0349 } 0350 }