Differences Between: [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403]
1 <?php 2 /** 3 * Copyright 1997-2017 Horde LLC (http://www.horde.org/) 4 * Copyright (c) 2002-2007, Richard Heyes 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * o Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * o Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * o The names of the authors may not be used to endorse or promote 17 * products derived from this software without specific prior written 18 * permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 * @category Horde 33 * @copyright 1997-2017 Horde LLC (http://www.horde.org/) 34 * @copyright 2002-2007 Richard Heyes 35 * @license http://www.horde.org/licenses/bsd New BSD License 36 * @package Mail 37 */ 38 39 /** 40 * Mail transport base class. 41 * 42 * @author Chuck Hagenbuch <chuck@horde.org> 43 * @author Richard Heyes <richard@phpguru.org> 44 * @author Michael Slusarz <slusarz@horde.org> 45 * @category Horde 46 * @copyright 1997-2017 Horde LLC (http://www.horde.org/) 47 * @copyright 2002-2007 Richard Heyes 48 * @license http://www.horde.org/licenses/bsd New BSD License 49 * @package Mail 50 * 51 * @property-read boolean $eai Does the transport driver support EAI (RFC 52 * 6532) headers? (@since 2.5.0) 53 */ 54 abstract class Horde_Mail_Transport 55 { 56 /** 57 * Line terminator used for separating header lines. 58 * 59 * @var string 60 */ 61 public $sep = PHP_EOL; 62 63 /** 64 * Configuration parameters. 65 * 66 * @var array 67 */ 68 protected $_params = array(); 69 70 /** 71 */ 72 public function __get($name) 73 { 74 switch ($name) { 75 case 'eai': 76 return false; 77 } 78 } 79 80 /** 81 * Send a message. 82 * 83 * @param mixed $recipients Either a comma-seperated list of recipients 84 * (RFC822 compliant), or an array of 85 * recipients, each RFC822 valid. This may 86 * contain recipients not specified in the 87 * headers, for Bcc:, resending messages, etc. 88 * @param array $headers The headers to send with the mail, in an 89 * associative array, where the array key is the 90 * header name (ie, 'Subject'), and the array 91 * value is the header value (ie, 'test'). The 92 * header produced from those values would be 93 * 'Subject: test'. 94 * If the '_raw' key exists, the value of this 95 * key will be used as the exact text for 96 * sending the message. 97 * @param mixed $body The full text of the message body, including 98 * any Mime parts, etc. Either a string or a 99 * stream resource. 100 * 101 * @throws Horde_Mail_Exception 102 */ 103 abstract public function send($recipients, array $headers, $body); 104 105 /** 106 * Take an array of mail headers and return a string containing text 107 * usable in sending a message. 108 * 109 * @param array $headers The array of headers to prepare, in an 110 * associative array, where the array key is the 111 * header name (ie, 'Subject'), and the array value 112 * is the header value (ie, 'test'). The header 113 * produced from those values would be 'Subject: 114 * test'. 115 * If the '_raw' key exists, the value of this key 116 * will be used as the exact text for sending the 117 * message. 118 * 119 * @return mixed Returns false if it encounters a bad address; otherwise 120 * returns an array containing two elements: Any From: 121 * address found in the headers, and the plain text version 122 * of the headers. 123 * @throws Horde_Mail_Exception 124 */ 125 public function prepareHeaders(array $headers) 126 { 127 $from = null; 128 $lines = array(); 129 $raw = isset($headers['_raw']) 130 ? $headers['_raw'] 131 : null; 132 133 foreach ($headers as $key => $value) { 134 if (strcasecmp($key, 'From') === 0) { 135 $parser = new Horde_Mail_Rfc822(); 136 $addresses = $parser->parseAddressList($value, array( 137 'validate' => $this->eai ? 'eai' : true 138 )); 139 $from = $addresses[0]->bare_address; 140 141 // Reject envelope From: addresses with spaces. 142 if (strstr($from, ' ')) { 143 return false; 144 } 145 146 $lines[] = $key . ': ' . $this->_normalizeEOL($value); 147 } elseif (!$raw && (strcasecmp($key, 'Received') === 0)) { 148 $received = array(); 149 if (!is_array($value)) { 150 $value = array($value); 151 } 152 153 foreach ($value as $line) { 154 $received[] = $key . ': ' . $this->_normalizeEOL($line); 155 } 156 157 // Put Received: headers at the top. Spam detectors often 158 // flag messages with Received: headers after the Subject: 159 // as spam. 160 $lines = array_merge($received, $lines); 161 } elseif (!$raw) { 162 // If $value is an array (i.e., a list of addresses), convert 163 // it to a comma-delimited string of its elements (addresses). 164 if (is_array($value)) { 165 $value = implode(', ', $value); 166 } 167 $lines[] = $key . ': ' . $this->_normalizeEOL($value); 168 } 169 } 170 171 return array($from, $raw ? $raw : implode($this->sep, $lines)); 172 } 173 174 /** 175 * Take a set of recipients and parse them, returning an array of bare 176 * addresses (forward paths) that can be passed to sendmail or an SMTP 177 * server with the 'RCPT TO:' command. 178 * 179 * @param mixed $recipients Either a comma-separated list of recipients 180 * (RFC822 compliant), or an array of 181 * recipients, each RFC822 valid. 182 * 183 * @return array Forward paths (bare addresses, IDN encoded). 184 * @throws Horde_Mail_Exception 185 */ 186 public function parseRecipients($recipients) 187 { 188 // Parse recipients, leaving out all personal info. This is 189 // for smtp recipients, etc. All relevant personal information 190 // should already be in the headers. 191 $rfc822 = new Horde_Mail_Rfc822(); 192 return $rfc822->parseAddressList($recipients, array( 193 'validate' => $this->eai ? 'eai' : true 194 ))->bare_addresses_idn; 195 } 196 197 /** 198 * Sanitize an array of mail headers by removing any additional header 199 * strings present in a legitimate header's value. The goal of this 200 * filter is to prevent mail injection attacks. 201 * 202 * Raw headers are sent as-is. 203 * 204 * @param array $headers The associative array of headers to sanitize. 205 * 206 * @return array The sanitized headers. 207 */ 208 protected function _sanitizeHeaders($headers) 209 { 210 foreach (array_diff(array_keys($headers), array('_raw')) as $key) { 211 $headers[$key] = preg_replace('=((<CR>|<LF>|0x0A/%0A|0x0D/%0D|\\n|\\r)\S).*=i', null, $headers[$key]); 212 } 213 214 return $headers; 215 } 216 217 /** 218 * Normalizes EOLs in string data. 219 * 220 * @param string $data Data. 221 * 222 * @return string Normalized data. 223 */ 224 protected function _normalizeEOL($data) 225 { 226 return strtr($data, array( 227 "\r\n" => $this->sep, 228 "\r" => $this->sep, 229 "\n" => $this->sep 230 )); 231 } 232 233 /** 234 * Get the from address. 235 * 236 * @param string $from From address. 237 * @param array $headers Headers array. 238 * 239 * @return string Address object. 240 * @throws Horde_Mail_Exception 241 */ 242 protected function _getFrom($from, $headers) 243 { 244 /* Since few MTAs are going to allow this header to be forged unless 245 * it's in the MAIL FROM: exchange, we'll use Return-Path instead of 246 * From: if it's set. */ 247 foreach (array_keys($headers) as $hdr) { 248 if (strcasecmp($hdr, 'Return-Path') === 0) { 249 $from = $headers[$hdr]; 250 break; 251 } 252 } 253 254 if (!strlen($from)) { 255 throw new Horde_Mail_Exception('No from address provided.'); 256 } 257 258 $from = new Horde_Mail_Rfc822_Address($from); 259 260 return $from->bare_address_idn; 261 } 262 263 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body