[ Index ] |
MailPress 7.2 |
[ Index ] [ Classes ] [ Functions ] [ Variables ] [ Constants ] [ Statistics ] |
[Summary view] [Print] [Text view]
1 <?php 2 3 /* 4 * This file is part of SwiftMailer. 5 * (c) 2004-2009 Chris Corbyn 6 * 7 * For the full copyright and license information, please view the LICENSE 8 * file that was distributed with this source code. 9 */ 10 11 /** 12 * Sends Messages over SMTP with ESMTP support. 13 * 14 * @author Chris Corbyn 15 */ 16 class Swift_Transport_EsmtpTransport extends Swift_Transport_AbstractSmtpTransport implements Swift_Transport_SmtpAgent 17 { 18 /** 19 * ESMTP extension handlers. 20 * 21 * @var Swift_Transport_EsmtpHandler[] 22 */ 23 private $handlers = []; 24 25 /** 26 * ESMTP capabilities. 27 * 28 * @var string[] 29 */ 30 private $capabilities = []; 31 32 /** 33 * Connection buffer parameters. 34 * 35 * @var array 36 */ 37 private $params = [ 38 'protocol' => 'tcp', 39 'host' => 'localhost', 40 'port' => 25, 41 'timeout' => 30, 42 'blocking' => 1, 43 'tls' => false, 44 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET, 45 'stream_context_options' => [], 46 ]; 47 48 /** 49 * Creates a new EsmtpTransport using the given I/O buffer. 50 * 51 * @param Swift_Transport_EsmtpHandler[] $extensionHandlers 52 * @param string $localDomain 53 */ 54 public function __construct(Swift_Transport_IoBuffer $buf, array $extensionHandlers, Swift_Events_EventDispatcher $dispatcher, $localDomain = '127.0.0.1', Swift_AddressEncoder $addressEncoder = null) 55 { 56 parent::__construct($buf, $dispatcher, $localDomain, $addressEncoder); 57 $this->setExtensionHandlers($extensionHandlers); 58 } 59 60 /** 61 * Set the host to connect to. 62 * 63 * Literal IPv6 addresses should be wrapped in square brackets. 64 * 65 * @param string $host 66 * 67 * @return $this 68 */ 69 public function setHost($host) 70 { 71 $this->params['host'] = $host; 72 73 return $this; 74 } 75 76 /** 77 * Get the host to connect to. 78 * 79 * @return string 80 */ 81 public function getHost() 82 { 83 return $this->params['host']; 84 } 85 86 /** 87 * Set the port to connect to. 88 * 89 * @param int $port 90 * 91 * @return $this 92 */ 93 public function setPort($port) 94 { 95 $this->params['port'] = (int) $port; 96 97 return $this; 98 } 99 100 /** 101 * Get the port to connect to. 102 * 103 * @return int 104 */ 105 public function getPort() 106 { 107 return $this->params['port']; 108 } 109 110 /** 111 * Set the connection timeout. 112 * 113 * @param int $timeout seconds 114 * 115 * @return $this 116 */ 117 public function setTimeout($timeout) 118 { 119 $this->params['timeout'] = (int) $timeout; 120 $this->buffer->setParam('timeout', (int) $timeout); 121 122 return $this; 123 } 124 125 /** 126 * Get the connection timeout. 127 * 128 * @return int 129 */ 130 public function getTimeout() 131 { 132 return $this->params['timeout']; 133 } 134 135 /** 136 * Set the encryption type (tls or ssl). 137 * 138 * @param string $encryption 139 * 140 * @return $this 141 */ 142 public function setEncryption($encryption) 143 { 144 $encryption = strtolower($encryption); 145 if ('tls' == $encryption) { 146 $this->params['protocol'] = 'tcp'; 147 $this->params['tls'] = true; 148 } else { 149 $this->params['protocol'] = $encryption; 150 $this->params['tls'] = false; 151 } 152 153 return $this; 154 } 155 156 /** 157 * Get the encryption type. 158 * 159 * @return string 160 */ 161 public function getEncryption() 162 { 163 return $this->params['tls'] ? 'tls' : $this->params['protocol']; 164 } 165 166 /** 167 * Sets the stream context options. 168 * 169 * @param array $options 170 * 171 * @return $this 172 */ 173 public function setStreamOptions($options) 174 { 175 $this->params['stream_context_options'] = $options; 176 177 return $this; 178 } 179 180 /** 181 * Returns the stream context options. 182 * 183 * @return array 184 */ 185 public function getStreamOptions() 186 { 187 return $this->params['stream_context_options']; 188 } 189 190 /** 191 * Sets the source IP. 192 * 193 * IPv6 addresses should be wrapped in square brackets. 194 * 195 * @param string $source 196 * 197 * @return $this 198 */ 199 public function setSourceIp($source) 200 { 201 $this->params['sourceIp'] = $source; 202 203 return $this; 204 } 205 206 /** 207 * Returns the IP used to connect to the destination. 208 * 209 * @return string 210 */ 211 public function getSourceIp() 212 { 213 return $this->params['sourceIp'] ?? null; 214 } 215 216 /** 217 * Sets whether SMTP pipelining is enabled. 218 * 219 * By default, support is auto-detected using the PIPELINING SMTP extension. 220 * Use this function to override that in the unlikely event of compatibility 221 * issues. 222 * 223 * @param bool $enabled 224 * 225 * @return $this 226 */ 227 public function setPipelining($enabled) 228 { 229 $this->pipelining = $enabled; 230 231 return $this; 232 } 233 234 /** 235 * Returns whether SMTP pipelining is enabled. 236 * 237 * @return bool|null a boolean if pipelining is explicitly enabled or disabled, 238 * or null if support is auto-detected. 239 */ 240 public function getPipelining() 241 { 242 return $this->pipelining; 243 } 244 245 /** 246 * Set ESMTP extension handlers. 247 * 248 * @param Swift_Transport_EsmtpHandler[] $handlers 249 * 250 * @return $this 251 */ 252 public function setExtensionHandlers(array $handlers) 253 { 254 $assoc = []; 255 foreach ($handlers as $handler) { 256 $assoc[$handler->getHandledKeyword()] = $handler; 257 } 258 uasort($assoc, function ($a, $b) { 259 return $a->getPriorityOver($b->getHandledKeyword()); 260 }); 261 $this->handlers = $assoc; 262 $this->setHandlerParams(); 263 264 return $this; 265 } 266 267 /** 268 * Get ESMTP extension handlers. 269 * 270 * @return Swift_Transport_EsmtpHandler[] 271 */ 272 public function getExtensionHandlers() 273 { 274 return array_values($this->handlers); 275 } 276 277 /** 278 * Run a command against the buffer, expecting the given response codes. 279 * 280 * If no response codes are given, the response will not be validated. 281 * If codes are given, an exception will be thrown on an invalid response. 282 * 283 * @param string $command 284 * @param int[] $codes 285 * @param string[] $failures An array of failures by-reference 286 * @param bool $pipeline Do not wait for response 287 * @param string $address The address, if command is RCPT TO. 288 * 289 * @return string|null The server response, or null if pipelining is enabled 290 */ 291 public function executeCommand($command, $codes = [], &$failures = null, $pipeline = false, $address = null) 292 { 293 $failures = (array) $failures; 294 $stopSignal = false; 295 $response = null; 296 foreach ($this->getActiveHandlers() as $handler) { 297 $response = $handler->onCommand( 298 $this, $command, $codes, $failures, $stopSignal 299 ); 300 if ($stopSignal) { 301 return $response; 302 } 303 } 304 305 return parent::executeCommand($command, $codes, $failures, $pipeline, $address); 306 } 307 308 /** Mixin handling method for ESMTP handlers */ 309 public function __call($method, $args) 310 { 311 foreach ($this->handlers as $handler) { 312 if (in_array(strtolower($method), 313 array_map('strtolower', (array) $handler->exposeMixinMethods()) 314 )) { 315 $return = call_user_func_array([$handler, $method], $args); 316 // Allow fluid method calls 317 if (null === $return && 'set' == substr($method, 0, 3)) { 318 return $this; 319 } else { 320 return $return; 321 } 322 } 323 } 324 trigger_error('Call to undefined method '.$method, E_USER_ERROR); 325 } 326 327 /** Get the params to initialize the buffer */ 328 protected function getBufferParams() 329 { 330 return $this->params; 331 } 332 333 /** Overridden to perform EHLO instead */ 334 protected function doHeloCommand() 335 { 336 try { 337 $response = $this->executeCommand( 338 sprintf("EHLO %s\r\n", $this->domain), [250] 339 ); 340 } catch (Swift_TransportException $e) { 341 return parent::doHeloCommand(); 342 } 343 344 if ($this->params['tls']) { 345 try { 346 $this->executeCommand("STARTTLS\r\n", [220]); 347 348 if (!$this->buffer->startTLS()) { 349 throw new Swift_TransportException('Unable to connect with TLS encryption'); 350 } 351 352 try { 353 $response = $this->executeCommand( 354 sprintf("EHLO %s\r\n", $this->domain), [250] 355 ); 356 } catch (Swift_TransportException $e) { 357 return parent::doHeloCommand(); 358 } 359 } catch (Swift_TransportException $e) { 360 $this->throwException($e); 361 } 362 } 363 364 $this->capabilities = $this->getCapabilities($response); 365 if (!isset($this->pipelining)) { 366 $this->pipelining = isset($this->capabilities['PIPELINING']); 367 } 368 369 $this->setHandlerParams(); 370 foreach ($this->getActiveHandlers() as $handler) { 371 $handler->afterEhlo($this); 372 } 373 } 374 375 /** Overridden to add Extension support */ 376 protected function doMailFromCommand($address) 377 { 378 $address = $this->addressEncoder->encodeString($address); 379 $handlers = $this->getActiveHandlers(); 380 $params = []; 381 foreach ($handlers as $handler) { 382 $params = array_merge($params, (array) $handler->getMailParams()); 383 } 384 $paramStr = !empty($params) ? ' '.implode(' ', $params) : ''; 385 $this->executeCommand( 386 sprintf("MAIL FROM:<%s>%s\r\n", $address, $paramStr), [250], $failures, true 387 ); 388 } 389 390 /** Overridden to add Extension support */ 391 protected function doRcptToCommand($address) 392 { 393 $address = $this->addressEncoder->encodeString($address); 394 $handlers = $this->getActiveHandlers(); 395 $params = []; 396 foreach ($handlers as $handler) { 397 $params = array_merge($params, (array) $handler->getRcptParams()); 398 } 399 $paramStr = !empty($params) ? ' '.implode(' ', $params) : ''; 400 $this->executeCommand( 401 sprintf("RCPT TO:<%s>%s\r\n", $address, $paramStr), [250, 251, 252], $failures, true, $address 402 ); 403 } 404 405 /** Determine ESMTP capabilities by function group */ 406 private function getCapabilities($ehloResponse) 407 { 408 $capabilities = []; 409 $ehloResponse = trim($ehloResponse); 410 $lines = explode("\r\n", $ehloResponse); 411 array_shift($lines); 412 foreach ($lines as $line) { 413 if (preg_match('/^[0-9]{3}[ -]([A-Z0-9-]+)((?:[ =].*)?)$/Di', $line, $matches)) { 414 $keyword = strtoupper($matches[1]); 415 $paramStr = strtoupper(ltrim($matches[2], ' =')); 416 $params = !empty($paramStr) ? explode(' ', $paramStr) : []; 417 $capabilities[$keyword] = $params; 418 } 419 } 420 421 return $capabilities; 422 } 423 424 /** Set parameters which are used by each extension handler */ 425 private function setHandlerParams() 426 { 427 foreach ($this->handlers as $keyword => $handler) { 428 if (array_key_exists($keyword, $this->capabilities)) { 429 $handler->setKeywordParams($this->capabilities[$keyword]); 430 } 431 } 432 } 433 434 /** Get ESMTP handlers which are currently ok to use */ 435 private function getActiveHandlers() 436 { 437 $handlers = []; 438 foreach ($this->handlers as $keyword => $handler) { 439 if (array_key_exists($keyword, $this->capabilities)) { 440 $handlers[] = $handler; 441 } 442 } 443 444 return $handlers; 445 } 446 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue May 19 15:55:14 2020 | Cross-referenced by PHPXref 0.7.1 |