Esempio n. 1
0
 /**
  * Connects to the smtp-server
  */
 protected function connect()
 {
     // connect
     $this->connection = new RemoteFile(MAIL_SMTP_HOST, MAIL_SMTP_PORT);
     $this->getSMTPStatus();
     if ($this->statusCode != 220) {
         throw new SystemException($this->formatError("can not connect to '" . MAIL_SMTP_HOST . ":" . MAIL_SMTP_PORT . "'"));
     }
     $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
     if (empty($host)) {
         $host = gethostname();
         if ($host === false) {
             $host = 'localhost';
         }
     }
     // send ehlo
     $this->write('EHLO ' . $host);
     $extensions = explode(Mail::$lineEnding, $this->read());
     $this->getSMTPStatus(array_shift($extensions));
     if ($this->statusCode == 250) {
         $extensions = array_map(function ($element) {
             return strtolower(substr($element, 4));
         }, $extensions);
         if ($this->connection->hasTLSSupport() && in_array('starttls', $extensions)) {
             $this->write('STARTTLS');
             $this->getSMTPStatus();
             if ($this->statusCode != 220) {
                 throw new SystemException($this->formatError("cannot enable STARTTLS, though '" . MAIL_SMTP_HOST . ":" . MAIL_SMTP_PORT . "' advertised it"));
             }
             if (!$this->connection->setTLS(true)) {
                 throw new SystemException('enabling TLS failed');
             }
             // repeat EHLO
             $this->write('EHLO ' . $host);
             $extensions = explode(Mail::$lineEnding, $this->read());
             $this->getSMTPStatus(array_shift($extensions));
             if ($this->statusCode != 250) {
                 throw new SystemException($this->formatError("could not EHLO after enabling STARTTLS at '" . MAIL_SMTP_HOST . ":" . MAIL_SMTP_PORT . "'"));
             }
         }
         // do authentication
         if (MAIL_SMTP_USER != '' || MAIL_SMTP_PASSWORD != '') {
             $this->auth();
         }
     } else {
         // send helo
         $this->write('HELO ' . $host);
         $this->getSMTPStatus();
         if ($this->statusCode != 250) {
             throw new SystemException($this->formatError("can not connect to '" . MAIL_SMTP_HOST . ":" . MAIL_SMTP_PORT . "'"));
         }
     }
 }
Esempio n. 2
0
 /**
  * Executes the HTTP request.
  */
 public function execute()
 {
     // connect
     $remoteFile = new RemoteFile(($this->useSSL ? 'ssl://' : '') . $this->host, $this->port, $this->options['timeout'], array('ssl' => array('peer_name' => $this->originHost)));
     if ($this->originUseSSL && PROXY_SERVER_HTTP) {
         if ($this->useSSL) {
             throw new SystemException("Unable to proxy HTTPS when using TLS for proxy connection");
         }
         $request = "CONNECT " . $this->originHost . ":" . $this->originPort . " HTTP/1.0\r\n";
         if (isset($this->headers['user-agent'])) {
             $request .= 'user-agent: ' . reset($this->headers['user-agent']) . "\r\n";
         }
         $request .= "Host: " . $this->originHost . ":" . $this->originPort . "\r\n";
         $request .= "\r\n";
         $remoteFile->puts($request);
         $this->replyHeaders = array();
         while (!$remoteFile->eof()) {
             $line = $remoteFile->gets();
             if (rtrim($line) === '') {
                 $this->parseReplyHeaders();
                 break;
             }
             $this->replyHeaders[] = $line;
         }
         if ($this->statusCode != 200) {
             throw new SystemException("Expected 200 Ok as reply to my CONNECT, got '" . $this->statusCode . "'");
         }
         $remoteFile->setTLS(true);
     }
     $request = $this->options['method'] . " " . $this->path . ($this->query ? '?' . $this->query : '') . " HTTP/1.1\r\n";
     // add headers
     foreach ($this->headers as $name => $values) {
         foreach ($values as $value) {
             $request .= $name . ": " . $value . "\r\n";
         }
     }
     $request .= "\r\n";
     // add post parameters
     if ($this->options['method'] !== 'GET') {
         $request .= $this->body . "\r\n\r\n";
     }
     $remoteFile->puts($request);
     $inHeader = true;
     $this->replyHeaders = array();
     $this->replyBody = '';
     $chunkLength = 0;
     $bodyLength = 0;
     $chunkedTransferRegex = new Regex('(^|,)[ \\t]*chunked[ \\t]*$', Regex::CASE_INSENSITIVE);
     // read http response, until one of is true
     // a) EOF is reached
     // b) bodyLength is at least maxLength
     // c) bodyLength is at least Content-Length
     while (!($remoteFile->eof() || isset($this->options['maxLength']) && $bodyLength >= $this->options['maxLength'] || isset($this->replyHeaders['content-length']) && $bodyLength >= end($this->replyHeaders['content-length']))) {
         if ($chunkLength) {
             if (isset($this->options['maxLength'])) {
                 $chunkLength = min($chunkLength, $this->options['maxLength'] - $bodyLength);
             }
             $line = $remoteFile->read($chunkLength);
         } else {
             if (!$inHeader && (!isset($this->replyHeaders['transfer-encoding']) || !$chunkedTransferRegex->match(end($this->replyHeaders['transfer-encoding'])))) {
                 $length = 1024;
                 if (isset($this->options['maxLength'])) {
                     $length = min($length, $this->options['maxLength'] - $bodyLength);
                 }
                 if (isset($this->replyHeaders['content-length'])) {
                     $length = min($length, end($this->replyHeaders['content-length']) - $bodyLength);
                 }
                 $line = $remoteFile->read($length);
             } else {
                 $line = $remoteFile->gets();
             }
         }
         if ($inHeader) {
             if (rtrim($line) === '') {
                 $inHeader = false;
                 $this->parseReplyHeaders();
                 continue;
             }
             $this->replyHeaders[] = $line;
         } else {
             if (isset($this->replyHeaders['transfer-encoding']) && $chunkedTransferRegex->match(end($this->replyHeaders['transfer-encoding']))) {
                 // last chunk finished
                 if ($chunkLength === 0) {
                     // read hex data and trash chunk-extension
                     list($hex) = explode(';', $line, 2);
                     $chunkLength = hexdec($hex);
                     // $chunkLength === 0 -> no more data
                     if ($chunkLength === 0) {
                         // clear remaining response
                         while (!$remoteFile->gets(1024)) {
                         }
                         // remove chunked from transfer-encoding
                         $this->replyHeaders['transfer-encoding'] = array_filter(array_map(function ($element) use($chunkedTransferRegex) {
                             return $chunkedTransferRegex->replace($element, '');
                         }, $this->replyHeaders['transfer-encoding']), 'trim');
                         if (empty($this->replyHeaders['transfer-encoding'])) {
                             unset($this->replyHeaders['transfer-encoding']);
                         }
                         // break out of main reading loop
                         break;
                     }
                 } else {
                     $this->replyBody .= $line;
                     $chunkLength -= strlen($line);
                     $bodyLength += strlen($line);
                     if ($chunkLength === 0) {
                         $remoteFile->read(2);
                     }
                     // CRLF
                 }
             } else {
                 $this->replyBody .= $line;
                 $bodyLength += strlen($line);
             }
         }
     }
     if (isset($this->options['maxLength'])) {
         $this->replyBody = substr($this->replyBody, 0, $this->options['maxLength']);
     }
     $remoteFile->close();
     $this->parseReply();
 }