PageRenderTime 29ms CodeModel.GetById 3ms RepoModel.GetById 0ms app.codeStats 1ms

/application/libraries/3rd_party/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php

http://github.com/tcm-project/tangocms
PHP | 361 lines | 223 code | 35 blank | 103 comment | 12 complexity | 6968d5ce49b272e9000796ce29f1ade5 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /*
  3. * This file is part of SwiftMailer.
  4. * (c) 2004-2009 Chris Corbyn
  5. *
  6. * For the full copyright and license information, please view the LICENSE
  7. * file that was distributed with this source code.
  8. */
  9. //@require 'Swift/Transport/AbstractSmtpTransport.php';
  10. //@require 'Swift/Transport/EsmtpHandler.php';
  11. //@require 'Swift/Transport/IoBuffer.php';
  12. //@require 'Swift/Transport/SmtpAgent.php';
  13. //@require 'Swift/TransportException.php';
  14. //@require 'Swift/Mime/Message.php';
  15. //@require 'Swift/Events/EventDispatcher.php';
  16. /**
  17. * Sends Messages over SMTP with ESMTP support.
  18. * @package Swift
  19. * @subpackage Transport
  20. * @author Chris Corbyn
  21. */
  22. class Swift_Transport_EsmtpTransport
  23. extends Swift_Transport_AbstractSmtpTransport
  24. implements Swift_Transport_SmtpAgent
  25. {
  26. /**
  27. * ESMTP extension handlers.
  28. * @var Swift_Transport_EsmtpHandler[]
  29. * @access private
  30. */
  31. private $_handlers = array();
  32. /**
  33. * ESMTP capabilities.
  34. * @var string[]
  35. * @access private
  36. */
  37. private $_capabilities = array();
  38. /**
  39. * Connection buffer parameters.
  40. * @var array
  41. * @access protected
  42. */
  43. private $_params = array(
  44. 'protocol' => 'tcp',
  45. 'host' => 'localhost',
  46. 'port' => 25,
  47. 'timeout' => 30,
  48. 'blocking' => 1,
  49. 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET,
  50. 'starttls' => false
  51. );
  52. /**
  53. * Creates a new EsmtpTransport using the given I/O buffer.
  54. * @param Swift_Transport_IoBuffer $buf
  55. * @param Swift_Transport_EsmtpHandler[] $extensionHandlers
  56. * @param Swift_Events_EventDispatcher $dispatcher
  57. */
  58. public function __construct(Swift_Transport_IoBuffer $buf,
  59. array $extensionHandlers, Swift_Events_EventDispatcher $dispatcher)
  60. {
  61. parent::__construct($buf, $dispatcher);
  62. $this->setExtensionHandlers($extensionHandlers);
  63. }
  64. /**
  65. * Set the host to connect to.
  66. * @param string $host
  67. */
  68. public function setHost($host)
  69. {
  70. $this->_params['host'] = $host;
  71. return $this;
  72. }
  73. /**
  74. * Get the host to connect to.
  75. * @return string
  76. */
  77. public function getHost()
  78. {
  79. return $this->_params['host'];
  80. }
  81. /**
  82. * Set the port to connect to.
  83. * @param int $port
  84. */
  85. public function setPort($port)
  86. {
  87. $this->_params['port'] = (int) $port;
  88. return $this;
  89. }
  90. /**
  91. * Get the port to connect to.
  92. * @return int
  93. */
  94. public function getPort()
  95. {
  96. return $this->_params['port'];
  97. }
  98. /**
  99. * Set the connection timeout.
  100. * @param int $timeout seconds
  101. */
  102. public function setTimeout($timeout)
  103. {
  104. $this->_params['timeout'] = (int) $timeout;
  105. return $this;
  106. }
  107. /**
  108. * Get the connection timeout.
  109. * @return int
  110. */
  111. public function getTimeout()
  112. {
  113. return $this->_params['timeout'];
  114. }
  115. /**
  116. * Set the encryption type (tls or ssl)
  117. * @param string $encryption
  118. */
  119. public function setEncryption($enc)
  120. {
  121. if ($enc == 'starttls') {
  122. $this->_params['protocol'] = 'tcp';
  123. $this->_params['starttls'] = true;
  124. }
  125. else
  126. {
  127. $this->_params['protocol'] = $enc;
  128. $this->_params['starttls'] = false;
  129. }
  130. return $this;
  131. }
  132. /**
  133. * Get the encryption type.
  134. * @return string
  135. */
  136. public function getEncryption()
  137. {
  138. return $this->_params['starttls'] ? 'starttls' : $this->_params['protocol'];
  139. }
  140. /**
  141. * Set ESMTP extension handlers.
  142. * @param Swift_Transport_EsmtpHandler[] $handlers
  143. */
  144. public function setExtensionHandlers(array $handlers)
  145. {
  146. $assoc = array();
  147. foreach ($handlers as $handler)
  148. {
  149. $assoc[$handler->getHandledKeyword()] = $handler;
  150. }
  151. uasort($assoc, array($this, '_sortHandlers'));
  152. $this->_handlers = $assoc;
  153. $this->_setHandlerParams();
  154. return $this;
  155. }
  156. /**
  157. * Get ESMTP extension handlers.
  158. * @return Swift_Transport_EsmtpHandler[]
  159. */
  160. public function getExtensionHandlers()
  161. {
  162. return array_values($this->_handlers);
  163. }
  164. /**
  165. * Run a command against the buffer, expecting the given response codes.
  166. * If no response codes are given, the response will not be validated.
  167. * If codes are given, an exception will be thrown on an invalid response.
  168. * @param string $command
  169. * @param int[] $codes
  170. * @param string[] &$failures
  171. * @return string
  172. */
  173. public function executeCommand($command, $codes = array(), &$failures = null)
  174. {
  175. $failures = (array) $failures;
  176. $stopSignal = false;
  177. $response = null;
  178. foreach ($this->_getActiveHandlers() as $handler)
  179. {
  180. $response = $handler->onCommand(
  181. $this, $command, $codes, $failures, $stopSignal
  182. );
  183. if ($stopSignal)
  184. {
  185. return $response;
  186. }
  187. }
  188. return parent::executeCommand($command, $codes, $failures);
  189. }
  190. // -- Mixin invocation code
  191. /** Mixin handling method for ESMTP handlers */
  192. public function __call($method, $args)
  193. {
  194. foreach ($this->_handlers as $handler)
  195. {
  196. if (in_array(strtolower($method),
  197. array_map('strtolower', (array) $handler->exposeMixinMethods())
  198. ))
  199. {
  200. $return = call_user_func_array(array($handler, $method), $args);
  201. //Allow fluid method calls
  202. if (is_null($return) && substr($method, 0, 3) == 'set')
  203. {
  204. return $this;
  205. }
  206. else
  207. {
  208. return $return;
  209. }
  210. }
  211. }
  212. trigger_error('Call to undefined method ' . $method, E_USER_ERROR);
  213. }
  214. // -- Protected methods
  215. /** Get the params to initialize the buffer */
  216. protected function _getBufferParams()
  217. {
  218. return $this->_params;
  219. }
  220. /** Overridden to perform EHLO instead */
  221. protected function _doHeloCommand()
  222. {
  223. try
  224. {
  225. $response = $this->executeCommand(
  226. sprintf("EHLO %s\r\n", $this->_domain), array(250)
  227. );
  228. }
  229. catch (Swift_TransportException $e)
  230. {
  231. return parent::_doHeloCommand();
  232. }
  233. if ($this->_params['starttls']) {
  234. $this->executeCommand("STARTTLS\r\n", array(220));
  235. if (!$this->_buffer->startTLS()) {
  236. throw new Swift_TransportException('Failed to enable TLS encryption');
  237. }
  238. $response = $this->executeCommand(
  239. sprintf("EHLO %s\r\n", $this->_domain), array(250)
  240. );
  241. }
  242. $this->_capabilities = $this->_getCapabilities($response);
  243. $this->_setHandlerParams();
  244. foreach ($this->_getActiveHandlers() as $handler)
  245. {
  246. $handler->afterEhlo($this);
  247. }
  248. }
  249. /** Overridden to add Extension support */
  250. protected function _doMailFromCommand($address)
  251. {
  252. $handlers = $this->_getActiveHandlers();
  253. $params = array();
  254. foreach ($handlers as $handler)
  255. {
  256. $params = array_merge($params, (array) $handler->getMailParams());
  257. }
  258. $paramStr = !empty($params) ? ' ' . implode(' ', $params) : '';
  259. $this->executeCommand(
  260. sprintf("MAIL FROM: <%s>%s\r\n", $address, $paramStr), array(250)
  261. );
  262. }
  263. /** Overridden to add Extension support */
  264. protected function _doRcptToCommand($address)
  265. {
  266. $handlers = $this->_getActiveHandlers();
  267. $params = array();
  268. foreach ($handlers as $handler)
  269. {
  270. $params = array_merge($params, (array) $handler->getRcptParams());
  271. }
  272. $paramStr = !empty($params) ? ' ' . implode(' ', $params) : '';
  273. $this->executeCommand(
  274. sprintf("RCPT TO: <%s>%s\r\n", $address, $paramStr), array(250, 251, 252)
  275. );
  276. }
  277. // -- Private methods
  278. /** Determine ESMTP capabilities by function group */
  279. private function _getCapabilities($ehloResponse)
  280. {
  281. $capabilities = array();
  282. $ehloResponse = trim($ehloResponse);
  283. $lines = explode("\r\n", $ehloResponse);
  284. array_shift($lines);
  285. foreach ($lines as $line)
  286. {
  287. if (preg_match('/^[0-9]{3}[ -]([A-Z0-9-]+)((?:[ =].*)?)$/Di', $line, $matches))
  288. {
  289. $keyword = strtoupper($matches[1]);
  290. $paramStr = strtoupper(ltrim($matches[2], ' ='));
  291. $params = !empty($paramStr) ? explode(' ', $paramStr) : array();
  292. $capabilities[$keyword] = $params;
  293. }
  294. }
  295. return $capabilities;
  296. }
  297. /** Set parameters which are used by each extension handler */
  298. private function _setHandlerParams()
  299. {
  300. foreach ($this->_handlers as $keyword => $handler)
  301. {
  302. if (array_key_exists($keyword, $this->_capabilities))
  303. {
  304. $handler->setKeywordParams($this->_capabilities[$keyword]);
  305. }
  306. }
  307. }
  308. /** Get ESMTP handlers which are currently ok to use */
  309. private function _getActiveHandlers()
  310. {
  311. $handlers = array();
  312. foreach ($this->_handlers as $keyword => $handler)
  313. {
  314. if (array_key_exists($keyword, $this->_capabilities))
  315. {
  316. $handlers[] = $handler;
  317. }
  318. }
  319. return $handlers;
  320. }
  321. /** Custom sort for extension handler ordering */
  322. private function _sortHandlers($a, $b)
  323. {
  324. return $a->getPriorityOver($b->getHandledKeyword());
  325. }
  326. }