Overview

Packages

  • CONTENIDO
  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentRssCreator
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
    • ScriptCookieDirective
  • mpAutoloaderClassMap
  • None
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SearchSolr
    • SmartyWrapper
    • UrlShortener
    • UserForum
    • Workflow
  • PluginManager
  • Setup
    • Form
    • GUI
    • Helper
      • Environment
      • Filesystem
      • MySQL
      • PHP
    • UpgradeJob
  • Smarty
    • Cacher
    • Compiler
    • Config
    • Debug
    • PluginsBlock
    • PluginsFilter
    • PluginsFunction
    • PluginsInternal
    • PluginsModifier
    • PluginsModifierCompiler
    • PluginsShared
    • Security
    • Template
    • TemplateResources
  • Swift
    • ByteStream
    • CharacterStream
    • Encoder
    • Events
    • KeyCache
    • Mailer
    • Mime
    • Plugins
    • Transport

Classes

  • Swift_FailoverTransport
  • Swift_LoadBalancedTransport
  • Swift_MailTransport
  • Swift_Plugins_Loggers_ArrayLogger
  • Swift_Plugins_Loggers_EchoLogger
  • Swift_SendmailTransport
  • Swift_SmtpTransport
  • Swift_Transport_AbstractSmtpTransport
  • Swift_Transport_Esmtp_Auth_CramMd5Authenticator
  • Swift_Transport_Esmtp_Auth_LoginAuthenticator
  • Swift_Transport_Esmtp_Auth_PlainAuthenticator
  • Swift_Transport_Esmtp_AuthHandler
  • Swift_Transport_EsmtpTransport
  • Swift_Transport_FailoverTransport
  • Swift_Transport_LoadBalancedTransport
  • Swift_Transport_MailTransport
  • Swift_Transport_SendmailTransport
  • Swift_Transport_SimpleMailInvoker
  • Swift_Transport_StreamBuffer

Interfaces

  • Swift_Plugins_Logger
  • Swift_Plugins_Pop_Pop3Exception
  • Swift_Transport
  • Swift_Transport_Esmtp_Authenticator
  • Swift_Transport_EsmtpHandler
  • Swift_Transport_IoBuffer
  • Swift_Transport_MailInvoker
  • Swift_Transport_SmtpAgent
  • Swift_TransportException
  • Overview
  • Package
  • Function
  • Todo
  • Download
  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.
 13:  *
 14:  * @package Swift
 15:  * @subpackage Transport
 16:  * @author Chris Corbyn
 17:  */
 18: abstract class Swift_Transport_AbstractSmtpTransport implements Swift_Transport
 19: {
 20:     /** Input-Output buffer for sending/receiving SMTP commands and responses */
 21:     protected $_buffer;
 22: 
 23:     /** Connection status */
 24:     protected $_started = false;
 25: 
 26:     /** The domain name to use in HELO command */
 27:     protected $_domain = '[127.0.0.1]';
 28: 
 29:     /** The event dispatching layer */
 30:     protected $_eventDispatcher;
 31: 
 32:     /** Source Ip */
 33:     protected $_sourceIp;
 34: 
 35:     /** Return an array of params for the Buffer */
 36:     abstract protected function _getBufferParams();
 37: 
 38:     /**
 39:      * Creates a new EsmtpTransport using the given I/O buffer.
 40:      *
 41:      * @param Swift_Transport_IoBuffer     $buf
 42:      * @param Swift_Events_EventDispatcher $dispatcher
 43:      */
 44:     public function __construct(Swift_Transport_IoBuffer $buf, Swift_Events_EventDispatcher $dispatcher)
 45:     {
 46:         $this->_eventDispatcher = $dispatcher;
 47:         $this->_buffer = $buf;
 48:         $this->_lookupHostname();
 49:     }
 50: 
 51:     /**
 52:      * Set the name of the local domain which Swift will identify itself as.
 53:      * This should be a fully-qualified domain name and should be truly the domain
 54:      * you're using.  If your server doesn't have a domain name, use the IP in square
 55:      * brackets (i.e. [127.0.0.1]).
 56:      *
 57:      * @param  string                                $domain
 58:      * @return Swift_Transport_AbstractSmtpTransport
 59:      */
 60:     public function setLocalDomain($domain)
 61:     {
 62:         $this->_domain = $domain;
 63: 
 64:         return $this;
 65:     }
 66: 
 67:     /**
 68:      * Get the name of the domain Swift will identify as.
 69:      *
 70:      * @return string
 71:      */
 72:     public function getLocalDomain()
 73:     {
 74:         return $this->_domain;
 75:     }
 76: 
 77:     /**
 78:      * Sets the sourceIp
 79:      * @param string $source
 80:      */
 81:     public function setSourceIp($source)
 82:     {
 83:         $this->_sourceIp=$source;
 84:     }
 85: 
 86:     /**
 87:      * Returns the ip used to connect to the destination
 88:      * @return string
 89:      */
 90:     public function getSourceIp()
 91:     {
 92:         return $this->_sourceIp;
 93:     }
 94: 
 95:     /**
 96:      * Start the SMTP connection.
 97:      */
 98:     public function start()
 99:     {
100:         if (!$this->_started) {
101:             if ($evt = $this->_eventDispatcher->createTransportChangeEvent($this)) {
102:                 $this->_eventDispatcher->dispatchEvent($evt, 'beforeTransportStarted');
103:                 if ($evt->bubbleCancelled()) {
104:                     return;
105:                 }
106:             }
107: 
108:             try {
109:                 $this->_buffer->initialize($this->_getBufferParams());
110:             } catch (Swift_TransportException $e) {
111:                 $this->_throwException($e);
112:             }
113:             $this->_readGreeting();
114:             $this->_doHeloCommand();
115: 
116:             if ($evt) {
117:                 $this->_eventDispatcher->dispatchEvent($evt, 'transportStarted');
118:             }
119: 
120:             $this->_started = true;
121:         }
122:     }
123: 
124:     /**
125:      * Test if an SMTP connection has been established.
126:      *
127:      * @return boolean
128:      */
129:     public function isStarted()
130:     {
131:         return $this->_started;
132:     }
133: 
134:     /**
135:      * Send the given Message.
136:      *
137:      * Recipient/sender data will be retrieved from the Message API.
138:      * The return value is the number of recipients who were accepted for delivery.
139:      *
140:      * @param Swift_Mime_Message $message
141:      * @param string[] &$failedRecipients to collect failures by-reference
142:      * @return int
143:      */
144:     public function send(Swift_Mime_Message $message, &$failedRecipients = null)
145:     {
146:         $sent = 0;
147:         $failedRecipients = (array) $failedRecipients;
148: 
149:         if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) {
150:             $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed');
151:             if ($evt->bubbleCancelled()) {
152:                 return 0;
153:             }
154:         }
155: 
156:         if (!$reversePath = $this->_getReversePath($message)) {
157:             throw new Swift_TransportException(
158:                 'Cannot send message without a sender address'
159:                 );
160:         }
161: 
162:         $to = (array) $message->getTo();
163:         $cc = (array) $message->getCc();
164:         $bcc = (array) $message->getBcc();
165: 
166:         $message->setBcc(array());
167: 
168:         try {
169:             $sent += $this->_sendTo($message, $reversePath, $to, $failedRecipients);
170:             $sent += $this->_sendCc($message, $reversePath, $cc, $failedRecipients);
171:             $sent += $this->_sendBcc($message, $reversePath, $bcc, $failedRecipients);
172:         } catch (Exception $e) {
173:             $message->setBcc($bcc);
174:             throw $e;
175:         }
176: 
177:         $message->setBcc($bcc);
178: 
179:         if ($evt) {
180:             if ($sent == count($to) + count($cc) + count($bcc)) {
181:                 $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS);
182:             } elseif ($sent > 0) {
183:                 $evt->setResult(Swift_Events_SendEvent::RESULT_TENTATIVE);
184:             } else {
185:                 $evt->setResult(Swift_Events_SendEvent::RESULT_FAILED);
186:             }
187:             $evt->setFailedRecipients($failedRecipients);
188:             $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
189:         }
190: 
191:         $message->generateId(); //Make sure a new Message ID is used
192: 
193:         return $sent;
194:     }
195: 
196:     /**
197:      * Stop the SMTP connection.
198:      */
199:     public function stop()
200:     {
201:         if ($this->_started) {
202:             if ($evt = $this->_eventDispatcher->createTransportChangeEvent($this)) {
203:                 $this->_eventDispatcher->dispatchEvent($evt, 'beforeTransportStopped');
204:                 if ($evt->bubbleCancelled()) {
205:                     return;
206:                 }
207:             }
208: 
209:             try {
210:                 $this->executeCommand("QUIT\r\n", array(221));
211:             } catch (Swift_TransportException $e) {}
212: 
213:             try {
214:                 $this->_buffer->terminate();
215: 
216:                 if ($evt) {
217:                     $this->_eventDispatcher->dispatchEvent($evt, 'transportStopped');
218:                 }
219:             } catch (Swift_TransportException $e) {
220:                 $this->_throwException($e);
221:             }
222:         }
223:         $this->_started = false;
224:     }
225: 
226:     /**
227:      * Register a plugin.
228:      *
229:      * @param Swift_Events_EventListener $plugin
230:      */
231:     public function registerPlugin(Swift_Events_EventListener $plugin)
232:     {
233:         $this->_eventDispatcher->bindEventListener($plugin);
234:     }
235: 
236:     /**
237:      * Reset the current mail transaction.
238:      */
239:     public function reset()
240:     {
241:         $this->executeCommand("RSET\r\n", array(250));
242:     }
243: 
244:     /**
245:      * Get the IoBuffer where read/writes are occurring.
246:      *
247:      * @return Swift_Transport_IoBuffer
248:      */
249:     public function getBuffer()
250:     {
251:         return $this->_buffer;
252:     }
253: 
254:     /**
255:      * Run a command against the buffer, expecting the given response codes.
256:      *
257:      * If no response codes are given, the response will not be validated.
258:      * If codes are given, an exception will be thrown on an invalid response.
259:      *
260:      * @param string $command
261:      * @param int[]  $codes
262:      * @param string[] &$failures
263:      * @return string
264:      */
265:     public function executeCommand($command, $codes = array(), &$failures = null)
266:     {
267:         $failures = (array) $failures;
268:         $seq = $this->_buffer->write($command);
269:         $response = $this->_getFullResponse($seq);
270:         if ($evt = $this->_eventDispatcher->createCommandEvent($this, $command, $codes)) {
271:             $this->_eventDispatcher->dispatchEvent($evt, 'commandSent');
272:         }
273:         $this->_assertResponseCode($response, $codes);
274: 
275:         return $response;
276:     }
277: 
278:     // -- Protected methods
279: 
280:     /** Read the opening SMTP greeting */
281:     protected function _readGreeting()
282:     {
283:         $this->_assertResponseCode($this->_getFullResponse(0), array(220));
284:     }
285: 
286:     /** Send the HELO welcome */
287:     protected function _doHeloCommand()
288:     {
289:         $this->executeCommand(
290:             sprintf("HELO %s\r\n", $this->_domain), array(250)
291:             );
292:     }
293: 
294:     /** Send the MAIL FROM command */
295:     protected function _doMailFromCommand($address)
296:     {
297:         $this->executeCommand(
298:             sprintf("MAIL FROM: <%s>\r\n", $address), array(250)
299:             );
300:     }
301: 
302:     /** Send the RCPT TO command */
303:     protected function _doRcptToCommand($address)
304:     {
305:         $this->executeCommand(
306:             sprintf("RCPT TO: <%s>\r\n", $address), array(250, 251, 252)
307:             );
308:     }
309: 
310:     /** Send the DATA command */
311:     protected function _doDataCommand()
312:     {
313:         $this->executeCommand("DATA\r\n", array(354));
314:     }
315: 
316:     /** Stream the contents of the message over the buffer */
317:     protected function _streamMessage(Swift_Mime_Message $message)
318:     {
319:         $this->_buffer->setWriteTranslations(array("\r\n." => "\r\n.."));
320:         try {
321:             $message->toByteStream($this->_buffer);
322:             $this->_buffer->flushBuffers();
323:         } catch (Swift_TransportException $e) {
324:             $this->_throwException($e);
325:         }
326:         $this->_buffer->setWriteTranslations(array());
327:         $this->executeCommand("\r\n.\r\n", array(250));
328:     }
329: 
330:     /** Determine the best-use reverse path for this message */
331:     protected function _getReversePath(Swift_Mime_Message $message)
332:     {
333:         $return = $message->getReturnPath();
334:         $sender = $message->getSender();
335:         $from = $message->getFrom();
336:         $path = null;
337:         if (!empty($return)) {
338:             $path = $return;
339:         } elseif (!empty($sender)) {
340:             // Don't use array_keys
341:             reset($sender); // Reset Pointer to first pos
342:             $path = key($sender); // Get key
343:         } elseif (!empty($from)) {
344:             reset($from); // Reset Pointer to first pos
345:             $path = key($from); // Get key
346:         }
347: 
348:         return $path;
349:     }
350: 
351:     /** Throw a TransportException, first sending it to any listeners */
352:     protected function _throwException(Swift_TransportException $e)
353:     {
354:         if ($evt = $this->_eventDispatcher->createTransportExceptionEvent($this, $e)) {
355:             $this->_eventDispatcher->dispatchEvent($evt, 'exceptionThrown');
356:             if (!$evt->bubbleCancelled()) {
357:                 throw $e;
358:             }
359:         } else {
360:             throw $e;
361:         }
362:     }
363: 
364:     /** Throws an Exception if a response code is incorrect */
365:     protected function _assertResponseCode($response, $wanted)
366:     {
367:         list($code) = sscanf($response, '%3d');
368:         $valid = (empty($wanted) || in_array($code, $wanted));
369: 
370:         if ($evt = $this->_eventDispatcher->createResponseEvent($this, $response,
371:             $valid))
372:         {
373:             $this->_eventDispatcher->dispatchEvent($evt, 'responseReceived');
374:         }
375: 
376:         if (!$valid) {
377:             $this->_throwException(
378:                 new Swift_TransportException(
379:                     'Expected response code ' . implode('/', $wanted) . ' but got code ' .
380:                     '"' . $code . '", with message "' . $response . '"'
381:                     )
382:                 );
383:         }
384:     }
385: 
386:     /** Get an entire multi-line response using its sequence number */
387:     protected function _getFullResponse($seq)
388:     {
389:         $response = '';
390:         try {
391:             do {
392:                 $line = $this->_buffer->readLine($seq);
393:                 $response .= $line;
394:             } while (null !== $line && false !== $line && ' ' != $line{3});
395:         } catch (Swift_TransportException $e) {
396:             $this->_throwException($e);
397:         }
398: 
399:         return $response;
400:     }
401: 
402:     // -- Private methods
403: 
404:     /** Send an email to the given recipients from the given reverse path */
405:     private function _doMailTransaction($message, $reversePath, array $recipients, array &$failedRecipients)
406:     {
407:         $sent = 0;
408:         $this->_doMailFromCommand($reversePath);
409:         foreach ($recipients as $forwardPath) {
410:             try {
411:                 $this->_doRcptToCommand($forwardPath);
412:                 $sent++;
413:             } catch (Swift_TransportException $e) {
414:                 $failedRecipients[] = $forwardPath;
415:             }
416:         }
417: 
418:         if ($sent != 0) {
419:             $this->_doDataCommand();
420:             $this->_streamMessage($message);
421:         } else {
422:             $this->reset();
423:         }
424: 
425:         return $sent;
426:     }
427: 
428:     /** Send a message to the given To: recipients */
429:     private function _sendTo(Swift_Mime_Message $message, $reversePath, array $to, array &$failedRecipients)
430:     {
431:         if (empty($to)) {
432:             return 0;
433:         }
434: 
435:         return $this->_doMailTransaction($message, $reversePath, array_keys($to),
436:             $failedRecipients);
437:     }
438: 
439:     /** Send a message to the given Cc: recipients */
440:     private function _sendCc(Swift_Mime_Message $message, $reversePath, array $cc, array &$failedRecipients)
441:     {
442:         if (empty($cc)) {
443:             return 0;
444:         }
445: 
446:         return $this->_doMailTransaction($message, $reversePath, array_keys($cc),
447:             $failedRecipients);
448:     }
449: 
450:     /** Send a message to all Bcc: recipients */
451:     private function _sendBcc(Swift_Mime_Message $message, $reversePath, array $bcc, array &$failedRecipients)
452:     {
453:         $sent = 0;
454:         foreach ($bcc as $forwardPath => $name) {
455:             $message->setBcc(array($forwardPath => $name));
456:             $sent += $this->_doMailTransaction(
457:                 $message, $reversePath, array($forwardPath), $failedRecipients
458:                 );
459:         }
460: 
461:         return $sent;
462:     }
463: 
464:     /** Try to determine the hostname of the server this is run on */
465:     private function _lookupHostname()
466:     {
467:         if (!empty($_SERVER['SERVER_NAME'])
468:             && $this->_isFqdn($_SERVER['SERVER_NAME']))
469:         {
470:             $this->_domain = $_SERVER['SERVER_NAME'];
471:         } elseif (!empty($_SERVER['SERVER_ADDR'])) {
472:             $this->_domain = sprintf('[%s]', $_SERVER['SERVER_ADDR']);
473:         }
474:     }
475: 
476:     /** Determine is the $hostname is a fully-qualified name */
477:     private function _isFqdn($hostname)
478:     {
479:         //We could do a really thorough check, but there's really no point
480:         if (false !== $dotPos = strpos($hostname, '.')) {
481:             return ($dotPos > 0) && ($dotPos != strlen($hostname) - 1);
482:         } else {
483:             return false;
484:         }
485:     }
486: 
487:     /**
488:      * Destructor.
489:      */
490:     public function __destruct()
491:     {
492:         $this->stop();
493:     }
494: }
495: 
CMS CONTENIDO 4.9.7 API documentation generated by ApiGen