Ejemplo n.º 1
0
 /**
  * Send a message.
  * @TODO: Implement the DIGEST-MD5 and GSSAPI auth protocol. Implement SSLv1
  * and v2 support.
  *
  * @param   \Hoa\Mail\Message  $message    Message.
  * @return  bool
  */
 public function send(Mail\Message $message)
 {
     $content = $message->getFormattedContent();
     $headers = $message->getHeaders();
     $client = $this->getClient();
     $client->connect();
     $this->ifNot(220, 'Not able to connect to the server');
     $domain = $message->getDomain($this->getUsername() ?: $headers['from']);
     $client->writeAll('EHLO ' . $domain . CRLF);
     $ehlo = preg_split('#' . CRLF . '250[\\-\\s]+#', $client->read(2048));
     if (true === in_array('STARTTLS', $ehlo)) {
         $client->writeAll('STARTTLS' . CRLF);
         $this->ifNot(220, 'Cannot start a TLS connection');
         if (true !== $client->enableEncryption(true, $client::ENCRYPTION_TLS)) {
             throw new Mail\Exception\Transport('Cannot enable a TLS connection.', 1);
         }
         $client->writeAll('EHLO ' . $domain . CRLF);
         $ehlo = preg_split('#' . CRLF . '250[\\-\\s]+#', $client->read(2048));
     }
     $matches = null;
     foreach ($ehlo as $entry) {
         if (0 !== preg_match('#^AUTH (.+)$#', $entry, $matches)) {
             break;
         }
     }
     if (empty($matches)) {
         throw new Mail\Exception\Transport('The server does not support authentication, we cannot ' . 'authenticate.', 2);
     }
     $auth = explode(' ', $matches[1]);
     $username = $this->getUsername();
     $password = $this->getPassword();
     if (true === in_array('PLAIN', $auth)) {
         $client->writeAll('AUTH PLAIN' . CRLF);
         $this->ifNot(334, 'Authentication failed (PLAIN)');
         $challenge = base64_encode("" . $username . "" . $password);
         $client->writeAll($challenge . CRLF);
         $this->ifNot(235, 'Wrong username or password');
     } elseif (true === in_array('LOGIN', $auth)) {
         $client->writeAll('AUTH LOGIN' . CRLF);
         $this->ifNot(334, 'Authentication failed (LOGIN)');
         $challenge = base64_encode($username);
         $client->writeAll($challenge . CRLF);
         $this->ifNot(334, 'Wrong username');
         $challenge = base64_encode($password);
         $client->writeAll($challenge . CRLF);
         $this->ifNot(235, 'Wrong password');
     } elseif (true === in_array('CRAM-MD5', $auth)) {
         $client->writeAll('AUTH CRAM-MD5' . CRLF);
         $line = $this->ifNot(334, 'Authentication failed (CRAM-MD5)');
         $handle = base64_decode(substr($line, 4));
         $challenge = base64_encode($username . ' ' . static::hmac($password, $handle));
         $client->writeAll($challenge . CRLF);
         $this->ifNot(235, 'Wrong username or password');
     } else {
         throw new Mail\Transport('%s does not support authentication algorithms available ' . 'on the server (%s).', 3, [__CLASS__, implode(', ', $auth)]);
     }
     $from = $message->getAddress($headers['from']);
     $client->writeAll('MAIL FROM: <' . $from . '>' . CRLF);
     $this->ifNot(250, 'Sender ' . $from . ' is wrong');
     foreach ($message->getRecipients() as $recipient) {
         $client->writeAll('RCPT TO: <' . $recipient . '>' . CRLF);
         $this->ifNot(250, 'Recipient ' . $recipient . ' is wrong');
     }
     $client->writeAll('DATA' . CRLF);
     $this->ifNot(354, 'Cannot send data');
     $client->writeAll($content . CRLF . '.' . CRLF);
     $this->ifNot(250, 'Something went wrong with data');
     $client->writeAll('QUIT' . CRLF);
     $this->ifNot(221, 'Cannot quit properly');
     $client->disconnect();
     return true;
 }
Ejemplo n.º 2
0
 /**
  * Send a message.
  * Timeouts are defined as the RFC2821 Section 4.5.3.2 suggests.
  *
  * @TODO: Implement the DIGEST-MD5 and GSSAPI auth protocol. Implement SSLv1
  * and v2 support.
  *
  * @param   \Hoa\Mail\Message  $message    Message.
  * @return  bool
  */
 public function send(Mail\Message $message)
 {
     $content = $message->getFormattedContent();
     $headers = $message->getHeaders();
     $client = $this->getClient();
     $client->connect();
     $client->setStreamBlocking(true);
     $client->setStreamTimeout(5 * 60);
     $this->ifNot(220, 'Not able to connect to the server', 'The server timed out while trying to connect.');
     $domain = $message->getDomain($this->getUsername() ?: $headers['from']);
     $client->writeAll('EHLO ' . $domain . CRLF);
     $ehlo = $this->ifNot(250, 'Not able to get supported extensions from the server.', 'The server timed out while answering to a `EHLO` command.');
     if (true === in_array('STARTTLS', $ehlo)) {
         $client->writeAll('STARTTLS' . CRLF);
         $this->ifNot(220, 'Cannot start a TLS connection', 'The server timed out while starting a TLS encryption.');
         if (true !== $client->enableEncryption(true, $client::ENCRYPTION_TLS)) {
             throw new Mail\Exception\Transport('Cannot enable a TLS connection.', 3);
         }
         $client->writeAll('EHLO ' . $domain . CRLF);
         $ehlo = $this->ifNot(250, 'Not able to get supported extensions from the server.', 'The server timed out while answering to a `EHLO` command ' . 'after having established a TLS connection.');
     }
     $matches = null;
     foreach ($ehlo as $entry) {
         if (0 !== preg_match('#^AUTH (.+)$#', $entry, $matches)) {
             break;
         }
     }
     if (empty($matches)) {
         throw new Mail\Exception\Transport('The server does not support authentication, we cannot ' . 'authenticate.', 4);
     }
     $auth = explode(' ', $matches[1]);
     $username = $this->getUsername();
     $password = $this->getPassword();
     if (true === in_array('PLAIN', $auth)) {
         $client->writeAll('AUTH PLAIN' . CRLF);
         $this->ifNot(334, 'Authentication failed (PLAIN)', 'The server timed out while answering to an `AUTH PLAIN` ' . 'authentication.');
         $challenge = base64_encode("" . $username . "" . $password);
         $client->writeAll($challenge . CRLF);
         $this->ifNot(235, 'Wrong username or password', 'The server timed out while asserting whether the password ' . 'is correct for an `AUTH PLAIN` authentication.');
     } elseif (true === in_array('LOGIN', $auth)) {
         $client->writeAll('AUTH LOGIN' . CRLF);
         $this->ifNot(334, 'Authentication failed (LOGIN)', 'The server timed out while answering to an `AUTH LOGIN` ' . 'authentication.');
         $challenge = base64_encode($username);
         $client->writeAll($challenge . CRLF);
         $this->ifNot(334, 'Wrong username', 'The server timed out while asserting whether the username ' . 'is correct for an `AUTH LOGIN` authentication.');
         $challenge = base64_encode($password);
         $client->writeAll($challenge . CRLF);
         $this->ifNot(235, 'Wrong password', 'The server timed out while asserting whether the password ' . 'is correct for an `AUTH LOGIN` authentication.');
     } elseif (true === in_array('CRAM-MD5', $auth)) {
         $client->writeAll('AUTH CRAM-MD5' . CRLF);
         $line = $this->ifNot(334, 'Authentication failed (CRAM-MD5)', 'The server timed out while answering to an `AUTH CRAM-MD5` ' . 'authentication.');
         $handle = base64_decode(substr($line, 4));
         $challenge = base64_encode($username . ' ' . static::hmac($password, $handle));
         $client->writeAll($challenge . CRLF);
         $this->ifNot(235, 'Wrong username or password', 'The server timed out while asserting whether the username ' . 'and password are correct for an `AUTH CRAM-MD5` authentication.');
     } else {
         throw new Mail\Transport('%s does not support authentication algorithms available ' . 'on the server (%s).', 5, [__CLASS__, implode(', ', $auth)]);
     }
     $client->setStreamTimeout(5 * 60);
     $from = $message->getAddress($headers['from']);
     $client->writeAll('MAIL FROM: <' . $from . '>' . CRLF);
     $this->ifNot(250, 'Sender ' . $from . ' is wrong', 'The server timed out while asserting whether the sender\'s  ' . 'email is correct.');
     $client->setStreamTimeout(5 * 60);
     foreach ($message->getRecipients() as $recipient) {
         $client->writeAll('RCPT TO: <' . $recipient . '>' . CRLF);
         $this->ifNot(250, 'Recipient ' . $recipient . ' is wrong', 'The server timed out while asserting whether the ' . 'recipient\'s emails are correct.');
     }
     $client->setStreamTimeout(5 * 60);
     $client->writeAll('DATA' . CRLF);
     $this->ifNot(354, 'Cannot send data', 'The server timed out while answering to a `DATA` command.');
     $client->setStreamTimeout(10 * 60);
     $client->writeAll($content . CRLF . '.' . CRLF);
     $this->ifNot(250, 'Something went wrong with data', 'The server timed out while asserting all the data have been ' . 'received correctly.');
     $client->writeAll('QUIT' . CRLF);
     $this->ifNot(221, 'Cannot quit properly', 'The server timed out while trying to quit properly.');
     $client->disconnect();
     return true;
 }