[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Copyright 2010-2014 Horde LLC (http://www.horde.org/) 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * o Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * o Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * o The names of the authors may not be used to endorse or promote 16 * products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * @category Horde 32 * @copyright 2010-2014 Horde LLC 33 * @license http://www.horde.org/licenses/bsd New BSD License 34 * @package Mail 35 */ 36 37 /** 38 * SMTP implementation. 39 * 40 * @author Chuck Hagenbuch <chuck@horde.org> 41 * @author Jon Parise <jon@php.net> 42 * @author Michael Slusarz <slusarz@horde.org> 43 * @category Horde 44 * @copyright 2010-2014 Horde LLC 45 * @license http://www.horde.org/licenses/bsd New BSD License 46 * @package Mail 47 */ 48 class Horde_Mail_Transport_Smtp extends Horde_Mail_Transport 49 { 50 /* Error: Failed to create a Net_SMTP object */ 51 const ERROR_CREATE = 10000; 52 53 /* Error: Failed to connect to SMTP server */ 54 const ERROR_CONNECT = 10001; 55 56 /* Error: SMTP authentication failure */ 57 const ERROR_AUTH = 10002; 58 59 /* Error: No From: address has been provided */ 60 const ERROR_FROM = 10003; 61 62 /* Error: Failed to set sender */ 63 const ERROR_SENDER = 10004; 64 65 /* Error: Failed to add recipient */ 66 const ERROR_RECIPIENT = 10005; 67 68 /* Error: Failed to send data */ 69 const ERROR_DATA = 10006; 70 71 /** 72 * The SMTP greeting. 73 * 74 * @var string 75 */ 76 public $greeting = null; 77 78 /** 79 * The SMTP queued response. 80 * 81 * @var string 82 */ 83 public $queuedAs = null; 84 85 /** 86 * SMTP connection object. 87 * 88 * @var Net_SMTP 89 */ 90 protected $_smtp = null; 91 92 /** 93 * The list of service extension parameters to pass to the Net_SMTP 94 * mailFrom() command. 95 * 96 * @var array 97 */ 98 protected $_extparams = array(); 99 100 /** 101 * Constructor. 102 * 103 * @param array $params Additional parameters: 104 * - auth: (mixed) SMTP authentication. 105 * This value may be set to true, false or the name of a 106 * specific authentication method. If the value is set to true, 107 * the Net_SMTP package will attempt to use the best 108 * authentication method advertised by the remote SMTP server. 109 * DEFAULT: false. 110 * - debug: (boolean) Activate SMTP debug mode? 111 * DEFAULT: false 112 * - host: (string) The server to connect to. 113 * DEFAULT: localhost 114 * - localhost: (string) Hostname or domain that will be sent to the 115 * remote SMTP server in the HELO / EHLO message. 116 * DEFAULT: localhost 117 * - password: (string) The password to use for SMTP auth. 118 * DEFAULT: NONE 119 * - persist: (boolean) Should the SMTP connection persist? 120 * DEFAULT: false 121 * - pipelining: (boolean) Use SMTP command pipelining. 122 * Use SMTP command pipelining (specified in RFC 2920) if 123 * the SMTP server supports it. This speeds up delivery 124 * over high-latency connections. 125 * DEFAULT: false (use default value from Net_SMTP) 126 * - port: (integer) The port to connect to. 127 * DEFAULT: 25 128 * - timeout: (integer) The SMTP connection timeout. 129 * DEFAULT: NONE 130 * - username: (string) The username to use for SMTP auth. 131 * DEFAULT: NONE 132 */ 133 public function __construct(array $params = array()) 134 { 135 $this->_params = array_merge(array( 136 'auth' => false, 137 'debug' => false, 138 'host' => 'localhost', 139 'localhost' => 'localhost', 140 'password' => '', 141 'persist' => false, 142 'pipelining' => false, 143 'port' => 25, 144 'timeout' => null, 145 'username' => '' 146 ), $params); 147 148 /* Destructor implementation to ensure that we disconnect from any 149 * potentially-alive persistent SMTP connections. */ 150 register_shutdown_function(array($this, 'disconnect')); 151 152 /* SMTP requires CRLF line endings. */ 153 $this->sep = "\r\n"; 154 } 155 156 /** 157 */ 158 public function send($recipients, array $headers, $body) 159 { 160 /* If we don't already have an SMTP object, create one. */ 161 $this->getSMTPObject(); 162 163 $headers = $this->_sanitizeHeaders($headers); 164 165 /* Make sure the message has a trailing newline. */ 166 if (is_resource($body)) { 167 fseek($body, -1, SEEK_END); 168 switch (fgetc($body)) { 169 case "\r": 170 if (fgetc($body) != "\n") { 171 fputs($body, "\n"); 172 } 173 break; 174 175 default: 176 fputs($body, "\r\n"); 177 break; 178 } 179 rewind($body); 180 } elseif (substr($body, -2, 0) != "\r\n") { 181 $body .= "\r\n"; 182 } 183 184 try { 185 list($from, $textHeaders) = $this->prepareHeaders($headers); 186 } catch (Horde_Mail_Exception $e) { 187 $this->_smtp->rset(); 188 throw $e; 189 } 190 191 try { 192 $from = $this->_getFrom($from, $headers); 193 } catch (Horde_Mail_Exception $e) { 194 $this->_smtp->rset(); 195 throw new Horde_Mail_Exception('No From: address has been provided', self::ERROR_FROM); 196 } 197 198 $params = ''; 199 foreach ($this->_extparams as $key => $val) { 200 $params .= ' ' . $key . (is_null($val) ? '' : '=' . $val); 201 } 202 203 $res = $this->_smtp->mailFrom($from, ltrim($params)); 204 if ($res instanceof PEAR_Error) { 205 $this->_error(sprintf("Failed to set sender: %s", $from), $res, self::ERROR_SENDER); 206 } 207 208 try { 209 $recipients = $this->parseRecipients($recipients); 210 } catch (Horde_Mail_Exception $e) { 211 $this->_smtp->rset(); 212 throw $e; 213 } 214 215 foreach ($recipients as $recipient) { 216 $res = $this->_smtp->rcptTo($recipient); 217 if ($res instanceof PEAR_Error) { 218 $this->_error("Failed to add recipient: $recipient", $res, self::ERROR_RECIPIENT); 219 } 220 } 221 222 /* Send the message's headers and the body as SMTP data. Net_SMTP does 223 * the necessary EOL conversions. */ 224 $res = $this->_smtp->data($body, $textHeaders); 225 list(,$args) = $this->_smtp->getResponse(); 226 227 if (preg_match("/Ok: queued as (.*)/", $args, $queued)) { 228 $this->queuedAs = $queued[1]; 229 } 230 231 /* We need the greeting; from it we can extract the authorative name 232 * of the mail server we've really connected to. Ideal if we're 233 * connecting to a round-robin of relay servers and need to track 234 * which exact one took the email */ 235 $this->greeting = $this->_smtp->getGreeting(); 236 237 if ($res instanceof PEAR_Error) { 238 $this->_error('Failed to send data', $res, self::ERROR_DATA); 239 } 240 241 /* If persistent connections are disabled, destroy our SMTP object. */ 242 if (!$this->_params['persist']) { 243 $this->disconnect(); 244 } 245 } 246 247 /** 248 * Connect to the SMTP server by instantiating a Net_SMTP object. 249 * 250 * @return Net_SMTP The SMTP object. 251 * @throws Horde_Mail_Exception 252 */ 253 public function getSMTPObject() 254 { 255 if ($this->_smtp) { 256 return $this->_smtp; 257 } 258 259 $this->_smtp = new Net_SMTP( 260 $this->_params['host'], 261 $this->_params['port'], 262 $this->_params['localhost'] 263 ); 264 265 /* Set pipelining. */ 266 if ($this->_params['pipelining']) { 267 $this->_smtp->pipelining = true; 268 } 269 270 /* If we still don't have an SMTP object at this point, fail. */ 271 if (!($this->_smtp instanceof Net_SMTP)) { 272 throw new Horde_Mail_Exception('Failed to create a Net_SMTP object', self::ERROR_CREATE); 273 } 274 275 /* Configure the SMTP connection. */ 276 if ($this->_params['debug']) { 277 $this->_smtp->setDebug(true); 278 } 279 280 /* Attempt to connect to the configured SMTP server. */ 281 $res = $this->_smtp->connect($this->_params['timeout']); 282 if ($res instanceof PEAR_Error) { 283 $this->_error('Failed to connect to ' . $this->_params['host'] . ':' . $this->_params['port'], $res, self::ERROR_CONNECT); 284 } 285 286 /* Attempt to authenticate if authentication has been enabled. */ 287 if ($this->_params['auth']) { 288 $method = is_string($this->_params['auth']) 289 ? $this->_params['auth'] 290 : ''; 291 292 $res = $this->_smtp->auth($this->_params['username'], $this->_params['password'], $method); 293 if ($res instanceof PEAR_Error) { 294 $this->_error("$method authentication failure", $res, self::ERROR_AUTH); 295 } 296 } 297 298 return $this->_smtp; 299 } 300 301 /** 302 * Add parameter associated with a SMTP service extension. 303 * 304 * @param string $keyword Extension keyword. 305 * @param string $value Any value the keyword needs. 306 */ 307 public function addServiceExtensionParameter($keyword, $value = null) 308 { 309 $this->_extparams[$keyword] = $value; 310 } 311 312 /** 313 * Disconnect and destroy the current SMTP connection. 314 * 315 * @return boolean True if the SMTP connection no longer exists. 316 */ 317 public function disconnect() 318 { 319 /* If we have an SMTP object, disconnect and destroy it. */ 320 if (is_object($this->_smtp) && $this->_smtp->disconnect()) { 321 $this->_smtp = null; 322 } 323 324 /* We are disconnected if we no longer have an SMTP object. */ 325 return ($this->_smtp === null); 326 } 327 328 /** 329 * Build a standardized string describing the current SMTP error. 330 * 331 * @param string $text Custom string describing the error context. 332 * @param PEAR_Error $error PEAR_Error object. 333 * @param integer $e_code Error code. 334 * 335 * @throws Horde_Mail_Exception 336 */ 337 protected function _error($text, $error, $e_code) 338 { 339 /* Split the SMTP response into a code and a response string. */ 340 list($code, $response) = $this->_smtp->getResponse(); 341 342 /* Abort current SMTP transaction. */ 343 $this->_smtp->rset(); 344 345 /* Build our standardized error string. */ 346 throw new Horde_Mail_Exception($text . ' [SMTP: ' . $error->getMessage() . " (code: $code, response: $response)]", $e_code); 347 } 348 349 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |