1: <?php
2:
3: 4: 5: 6: 7: 8: 9:
10:
11: 12: 13: 14: 15: 16:
17: class Swift_Transport_EsmtpTransport extends Swift_Transport_AbstractSmtpTransport implements Swift_Transport_SmtpAgent
18: {
19: 20: 21: 22: 23:
24: private $_handlers = array();
25:
26: 27: 28: 29: 30:
31: private $_capabilities = array();
32:
33: 34: 35: 36: 37:
38: private $_params = array(
39: 'protocol' => 'tcp',
40: 'host' => 'localhost',
41: 'port' => 25,
42: 'timeout' => 30,
43: 'blocking' => 1,
44: 'tls' => false,
45: 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET
46: );
47:
48: 49: 50: 51: 52: 53:
54: public function __construct(Swift_Transport_IoBuffer $buf, array $extensionHandlers, Swift_Events_EventDispatcher $dispatcher)
55: {
56: parent::__construct($buf, $dispatcher);
57: $this->setExtensionHandlers($extensionHandlers);
58: }
59:
60: 61: 62: 63: 64:
65: public function setHost($host)
66: {
67: $this->_params['host'] = $host;
68:
69: return $this;
70: }
71:
72: 73: 74: 75:
76: public function getHost()
77: {
78: return $this->_params['host'];
79: }
80:
81: 82: 83: 84: 85:
86: public function setPort($port)
87: {
88: $this->_params['port'] = (int) $port;
89:
90: return $this;
91: }
92:
93: 94: 95: 96:
97: public function getPort()
98: {
99: return $this->_params['port'];
100: }
101:
102: 103: 104: 105: 106:
107: public function setTimeout($timeout)
108: {
109: $this->_params['timeout'] = (int) $timeout;
110: $this->_buffer->setParam('timeout', (int) $timeout);
111:
112: return $this;
113: }
114:
115: 116: 117: 118:
119: public function getTimeout()
120: {
121: return $this->_params['timeout'];
122: }
123:
124: 125: 126: 127: 128:
129: public function setEncryption($enc)
130: {
131: if ('tls' == $enc) {
132: $this->_params['protocol'] = 'tcp';
133: $this->_params['tls'] = true;
134: } else {
135: $this->_params['protocol'] = $enc;
136: $this->_params['tls'] = false;
137: }
138:
139: return $this;
140: }
141:
142: 143: 144: 145:
146: public function getEncryption()
147: {
148: return $this->_params['tls'] ? 'tls' : $this->_params['protocol'];
149: }
150:
151: 152: 153: 154: 155:
156: public function setSourceIp($source)
157: {
158: $this->_params['sourceIp']=$source;
159:
160: return $this;
161: }
162:
163: 164: 165: 166:
167: public function getSourceIp()
168: {
169: return $this->_params['sourceIp'];
170: }
171:
172: 173: 174: 175: 176:
177: public function setExtensionHandlers(array $handlers)
178: {
179: $assoc = array();
180: foreach ($handlers as $handler) {
181: $assoc[$handler->getHandledKeyword()] = $handler;
182: }
183: uasort($assoc, array($this, '_sortHandlers'));
184: $this->_handlers = $assoc;
185: $this->_setHandlerParams();
186:
187: return $this;
188: }
189:
190: 191: 192: 193:
194: public function getExtensionHandlers()
195: {
196: return array_values($this->_handlers);
197: }
198:
199: 200: 201: 202: 203: 204: 205: 206: 207:
208: public function executeCommand($command, $codes = array(), &$failures = null)
209: {
210: $failures = (array) $failures;
211: $stopSignal = false;
212: $response = null;
213: foreach ($this->_getActiveHandlers() as $handler) {
214: $response = $handler->onCommand(
215: $this, $command, $codes, $failures, $stopSignal
216: );
217: if ($stopSignal) {
218: return $response;
219: }
220: }
221:
222: return parent::executeCommand($command, $codes, $failures);
223: }
224:
225:
226:
227:
228: public function __call($method, $args)
229: {
230: foreach ($this->_handlers as $handler) {
231: if (in_array(strtolower($method),
232: array_map('strtolower', (array) $handler->exposeMixinMethods())
233: ))
234: {
235: $return = call_user_func_array(array($handler, $method), $args);
236:
237: if (is_null($return) && substr($method, 0, 3) == 'set') {
238: return $this;
239: } else {
240: return $return;
241: }
242: }
243: }
244: trigger_error('Call to undefined method ' . $method, E_USER_ERROR);
245: }
246:
247:
248:
249:
250: protected function _getBufferParams()
251: {
252: return $this->_params;
253: }
254:
255:
256: protected function _doHeloCommand()
257: {
258: try {
259: $response = $this->executeCommand(
260: sprintf("EHLO %s\r\n", $this->_domain), array(250)
261: );
262: } catch (Swift_TransportException $e) {
263: return parent::_doHeloCommand();
264: }
265:
266: if ($this->_params['tls']) {
267: try {
268: $this->executeCommand("STARTTLS\r\n", array(220));
269:
270: if (!$this->_buffer->startTLS()) {
271: throw new Swift_TransportException('Unable to connect with TLS encryption');
272: }
273:
274: try {
275: $response = $this->executeCommand(
276: sprintf("EHLO %s\r\n", $this->_domain), array(250)
277: );
278: } catch (Swift_TransportException $e) {
279: return parent::_doHeloCommand();
280: }
281: } catch (Swift_TransportException $e) {
282: $this->_throwException($e);
283: }
284: }
285:
286: $this->_capabilities = $this->_getCapabilities($response);
287: $this->_setHandlerParams();
288: foreach ($this->_getActiveHandlers() as $handler) {
289: $handler->afterEhlo($this);
290: }
291: }
292:
293:
294: protected function _doMailFromCommand($address)
295: {
296: $handlers = $this->_getActiveHandlers();
297: $params = array();
298: foreach ($handlers as $handler) {
299: $params = array_merge($params, (array) $handler->getMailParams());
300: }
301: $paramStr = !empty($params) ? ' ' . implode(' ', $params) : '';
302: $this->executeCommand(
303: sprintf("MAIL FROM: <%s>%s\r\n", $address, $paramStr), array(250)
304: );
305: }
306:
307:
308: protected function _doRcptToCommand($address)
309: {
310: $handlers = $this->_getActiveHandlers();
311: $params = array();
312: foreach ($handlers as $handler) {
313: $params = array_merge($params, (array) $handler->getRcptParams());
314: }
315: $paramStr = !empty($params) ? ' ' . implode(' ', $params) : '';
316: $this->executeCommand(
317: sprintf("RCPT TO: <%s>%s\r\n", $address, $paramStr), array(250, 251, 252)
318: );
319: }
320:
321:
322:
323:
324: private function _getCapabilities($ehloResponse)
325: {
326: $capabilities = array();
327: $ehloResponse = trim($ehloResponse);
328: $lines = explode("\r\n", $ehloResponse);
329: array_shift($lines);
330: foreach ($lines as $line) {
331: if (preg_match('/^[0-9]{3}[ -]([A-Z0-9-]+)((?:[ =].*)?)$/Di', $line, $matches)) {
332: $keyword = strtoupper($matches[1]);
333: $paramStr = strtoupper(ltrim($matches[2], ' ='));
334: $params = !empty($paramStr) ? explode(' ', $paramStr) : array();
335: $capabilities[$keyword] = $params;
336: }
337: }
338:
339: return $capabilities;
340: }
341:
342:
343: private function _setHandlerParams()
344: {
345: foreach ($this->_handlers as $keyword => $handler) {
346: if (array_key_exists($keyword, $this->_capabilities)) {
347: $handler->setKeywordParams($this->_capabilities[$keyword]);
348: }
349: }
350: }
351:
352:
353: private function _getActiveHandlers()
354: {
355: $handlers = array();
356: foreach ($this->_handlers as $keyword => $handler) {
357: if (array_key_exists($keyword, $this->_capabilities)) {
358: $handlers[] = $handler;
359: }
360: }
361:
362: return $handlers;
363: }
364:
365:
366: private function _sortHandlers($a, $b)
367: {
368: return $a->getPriorityOver($b->getHandledKeyword());
369: }
370: }
371: