update patch 1
This commit is contained in:
@@ -34,7 +34,7 @@ class CramMd5Authenticator implements AuthenticatorInterface
|
||||
$challenge = $client->executeCommand("AUTH CRAM-MD5\r\n", [334]);
|
||||
$challenge = base64_decode(substr($challenge, 4));
|
||||
$message = base64_encode($client->getUsername().' '.$this->getResponse($client->getPassword(), $challenge));
|
||||
$client->executeCommand(sprintf("%s\r\n", $message), [235]);
|
||||
$client->executeCommand(\sprintf("%s\r\n", $message), [235]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,8 +58,7 @@ class CramMd5Authenticator implements AuthenticatorInterface
|
||||
$kopad = substr($secret, 0, 64) ^ str_repeat(\chr(0x5C), 64);
|
||||
|
||||
$inner = pack('H32', md5($kipad.$challenge));
|
||||
$digest = md5($kopad.$inner);
|
||||
|
||||
return $digest;
|
||||
return md5($kopad.$inner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class LoginAuthenticator implements AuthenticatorInterface
|
||||
public function authenticate(EsmtpTransport $client): void
|
||||
{
|
||||
$client->executeCommand("AUTH LOGIN\r\n", [334]);
|
||||
$client->executeCommand(sprintf("%s\r\n", base64_encode($client->getUsername())), [334]);
|
||||
$client->executeCommand(sprintf("%s\r\n", base64_encode($client->getPassword())), [235]);
|
||||
$client->executeCommand(\sprintf("%s\r\n", base64_encode($client->getUsername())), [334]);
|
||||
$client->executeCommand(\sprintf("%s\r\n", base64_encode($client->getPassword())), [235]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,6 @@ class PlainAuthenticator implements AuthenticatorInterface
|
||||
*/
|
||||
public function authenticate(EsmtpTransport $client): void
|
||||
{
|
||||
$client->executeCommand(sprintf("AUTH PLAIN %s\r\n", base64_encode($client->getUsername().\chr(0).$client->getUsername().\chr(0).$client->getPassword())), [235]);
|
||||
$client->executeCommand(\sprintf("AUTH PLAIN %s\r\n", base64_encode($client->getUsername().\chr(0).$client->getUsername().\chr(0).$client->getPassword())), [235]);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-6
@@ -142,10 +142,10 @@ class EsmtpTransport extends SmtpTransport
|
||||
private function doEhloCommand(): string
|
||||
{
|
||||
try {
|
||||
$response = $this->executeCommand(sprintf("EHLO %s\r\n", $this->getLocalDomain()), [250]);
|
||||
$response = $this->executeCommand(\sprintf("EHLO %s\r\n", $this->getLocalDomain()), [250]);
|
||||
} catch (TransportExceptionInterface $e) {
|
||||
try {
|
||||
return parent::executeCommand(sprintf("HELO %s\r\n", $this->getLocalDomain()), [250]);
|
||||
return parent::executeCommand(\sprintf("HELO %s\r\n", $this->getLocalDomain()), [250]);
|
||||
} catch (TransportExceptionInterface $ex) {
|
||||
if (!$ex->getCode()) {
|
||||
throw $e;
|
||||
@@ -169,7 +169,7 @@ class EsmtpTransport extends SmtpTransport
|
||||
throw new TransportException('Unable to connect with STARTTLS.');
|
||||
}
|
||||
|
||||
$response = $this->executeCommand(sprintf("EHLO %s\r\n", $this->getLocalDomain()), [250]);
|
||||
$response = $this->executeCommand(\sprintf("EHLO %s\r\n", $this->getLocalDomain()), [250]);
|
||||
$this->capabilities = $this->parseCapabilities($response);
|
||||
}
|
||||
|
||||
@@ -195,6 +195,11 @@ class EsmtpTransport extends SmtpTransport
|
||||
return $capabilities;
|
||||
}
|
||||
|
||||
protected function serverSupportsSmtpUtf8(): bool
|
||||
{
|
||||
return \array_key_exists('SMTPUTF8', $this->capabilities);
|
||||
}
|
||||
|
||||
private function handleAuth(array $modes): void
|
||||
{
|
||||
if (!$this->username) {
|
||||
@@ -231,12 +236,12 @@ class EsmtpTransport extends SmtpTransport
|
||||
}
|
||||
|
||||
if (!$authNames) {
|
||||
throw new TransportException(sprintf('Failed to find an authenticator supported by the SMTP server, which currently supports: "%s".', implode('", "', $modes)), $code ?: 504);
|
||||
throw new TransportException(\sprintf('Failed to find an authenticator supported by the SMTP server, which currently supports: "%s".', implode('", "', $modes)), $code ?: 504);
|
||||
}
|
||||
|
||||
$message = sprintf('Failed to authenticate on SMTP server with username "%s" using the following authenticators: "%s".', $this->username, implode('", "', $authNames));
|
||||
$message = \sprintf('Failed to authenticate on SMTP server with username "%s" using the following authenticators: "%s".', $this->username, implode('", "', $authNames));
|
||||
foreach ($errors as $name => $error) {
|
||||
$message .= sprintf(' Authenticator "%s" returned "%s".', $name, $error);
|
||||
$message .= \sprintf(' Authenticator "%s" returned "%s".', $name, $error);
|
||||
}
|
||||
|
||||
throw new TransportException($message, $code ?: 535);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\Mailer\Transport\Smtp;
|
||||
|
||||
use Symfony\Component\Mailer\Exception\UnsupportedSchemeException;
|
||||
use Symfony\Component\Mailer\Transport\AbstractTransportFactory;
|
||||
use Symfony\Component\Mailer\Transport\Dsn;
|
||||
use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream;
|
||||
@@ -23,6 +24,10 @@ final class EsmtpTransportFactory extends AbstractTransportFactory
|
||||
{
|
||||
public function create(Dsn $dsn): TransportInterface
|
||||
{
|
||||
if (!\in_array($dsn->getScheme(), $this->getSupportedSchemes(), true)) {
|
||||
throw new UnsupportedSchemeException($dsn, 'smtp', $this->getSupportedSchemes());
|
||||
}
|
||||
|
||||
$autoTls = '' === $dsn->getOption('auto_tls') || filter_var($dsn->getOption('auto_tls', true), \FILTER_VALIDATE_BOOL);
|
||||
$tls = 'smtps' === $dsn->getScheme() ? true : ($autoTls ? null : false);
|
||||
$port = $dsn->getPort(0);
|
||||
|
||||
+25
-16
@@ -14,6 +14,7 @@ namespace Symfony\Component\Mailer\Transport\Smtp;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Mailer\Envelope;
|
||||
use Symfony\Component\Mailer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Mailer\Exception\LogicException;
|
||||
use Symfony\Component\Mailer\Exception\TransportException;
|
||||
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
|
||||
@@ -171,7 +172,7 @@ class SmtpTransport extends AbstractTransport
|
||||
public function __toString(): string
|
||||
{
|
||||
if ($this->stream instanceof SocketStream) {
|
||||
$name = sprintf('smtp%s://%s', ($tls = $this->stream->isTLS()) ? 's' : '', $this->stream->getHost());
|
||||
$name = \sprintf('smtp%s://%s', ($tls = $this->stream->isTLS()) ? 's' : '', $this->stream->getHost());
|
||||
$port = $this->stream->getPort();
|
||||
if (!(25 === $port || ($tls && 465 === $port))) {
|
||||
$name .= ':'.$port;
|
||||
@@ -211,7 +212,7 @@ class SmtpTransport extends AbstractTransport
|
||||
|
||||
try {
|
||||
$envelope = $message->getEnvelope();
|
||||
$this->doMailFromCommand($envelope->getSender()->getEncodedAddress());
|
||||
$this->doMailFromCommand($envelope->getSender()->getEncodedAddress(), $envelope->anyAddressHasUnicodeLocalpart());
|
||||
foreach ($envelope->getRecipients() as $recipient) {
|
||||
$this->doRcptToCommand($recipient->getEncodedAddress());
|
||||
}
|
||||
@@ -227,7 +228,7 @@ class SmtpTransport extends AbstractTransport
|
||||
} catch (\Exception $e) {
|
||||
$this->stream->terminate();
|
||||
$this->started = false;
|
||||
$this->getLogger()->debug(sprintf('Email transport "%s" stopped', __CLASS__));
|
||||
$this->getLogger()->debug(\sprintf('Email transport "%s" stopped', __CLASS__));
|
||||
throw $e;
|
||||
}
|
||||
$mtaResult = $this->executeCommand("\r\n.\r\n", [250]);
|
||||
@@ -244,19 +245,27 @@ class SmtpTransport extends AbstractTransport
|
||||
}
|
||||
}
|
||||
|
||||
private function doHeloCommand(): void
|
||||
protected function serverSupportsSmtpUtf8(): bool
|
||||
{
|
||||
$this->executeCommand(sprintf("HELO %s\r\n", $this->domain), [250]);
|
||||
return false;
|
||||
}
|
||||
|
||||
private function doMailFromCommand(string $address): void
|
||||
private function doHeloCommand(): void
|
||||
{
|
||||
$this->executeCommand(sprintf("MAIL FROM:<%s>\r\n", $address), [250]);
|
||||
$this->executeCommand(\sprintf("HELO %s\r\n", $this->domain), [250]);
|
||||
}
|
||||
|
||||
private function doMailFromCommand(string $address, bool $smtputf8): void
|
||||
{
|
||||
if ($smtputf8 && !$this->serverSupportsSmtpUtf8()) {
|
||||
throw new InvalidArgumentException('Invalid addresses: non-ASCII characters not supported in local-part of email.');
|
||||
}
|
||||
$this->executeCommand(\sprintf("MAIL FROM:<%s>%s\r\n", $address, $smtputf8 ? ' SMTPUTF8' : ''), [250]);
|
||||
}
|
||||
|
||||
private function doRcptToCommand(string $address): void
|
||||
{
|
||||
$this->executeCommand(sprintf("RCPT TO:<%s>\r\n", $address), [250, 251, 252]);
|
||||
$this->executeCommand(\sprintf("RCPT TO:<%s>\r\n", $address), [250, 251, 252]);
|
||||
}
|
||||
|
||||
public function start(): void
|
||||
@@ -265,7 +274,7 @@ class SmtpTransport extends AbstractTransport
|
||||
return;
|
||||
}
|
||||
|
||||
$this->getLogger()->debug(sprintf('Email transport "%s" starting', __CLASS__));
|
||||
$this->getLogger()->debug(\sprintf('Email transport "%s" starting', __CLASS__));
|
||||
|
||||
$this->stream->initialize();
|
||||
$this->assertResponseCode($this->getFullResponse(), [220]);
|
||||
@@ -273,7 +282,7 @@ class SmtpTransport extends AbstractTransport
|
||||
$this->started = true;
|
||||
$this->lastMessageTime = 0;
|
||||
|
||||
$this->getLogger()->debug(sprintf('Email transport "%s" started', __CLASS__));
|
||||
$this->getLogger()->debug(\sprintf('Email transport "%s" started', __CLASS__));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -289,7 +298,7 @@ class SmtpTransport extends AbstractTransport
|
||||
return;
|
||||
}
|
||||
|
||||
$this->getLogger()->debug(sprintf('Email transport "%s" stopping', __CLASS__));
|
||||
$this->getLogger()->debug(\sprintf('Email transport "%s" stopping', __CLASS__));
|
||||
|
||||
try {
|
||||
$this->executeCommand("QUIT\r\n", [221]);
|
||||
@@ -297,7 +306,7 @@ class SmtpTransport extends AbstractTransport
|
||||
} finally {
|
||||
$this->stream->terminate();
|
||||
$this->started = false;
|
||||
$this->getLogger()->debug(sprintf('Email transport "%s" stopped', __CLASS__));
|
||||
$this->getLogger()->debug(\sprintf('Email transport "%s" stopped', __CLASS__));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,10 +336,10 @@ class SmtpTransport extends AbstractTransport
|
||||
$valid = \in_array($code, $codes);
|
||||
|
||||
if (!$valid || !$response) {
|
||||
$codeStr = $code ? sprintf('code "%s"', $code) : 'empty code';
|
||||
$responseStr = $response ? sprintf(', with message "%s"', trim($response)) : '';
|
||||
$codeStr = $code ? \sprintf('code "%s"', $code) : 'empty code';
|
||||
$responseStr = $response ? \sprintf(', with message "%s"', trim($response)) : '';
|
||||
|
||||
throw new UnexpectedResponseException(sprintf('Expected response code "%s" but got ', implode('/', $codes)).$codeStr.$responseStr.'.', $code ?: 0);
|
||||
throw new UnexpectedResponseException(\sprintf('Expected response code "%s" but got ', implode('/', $codes)).$codeStr.$responseStr.'.', $code ?: 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,7 +368,7 @@ class SmtpTransport extends AbstractTransport
|
||||
|
||||
$this->stop();
|
||||
if (0 < $sleep = $this->restartThresholdSleep) {
|
||||
$this->getLogger()->debug(sprintf('Email transport "%s" sleeps for %d seconds after stopping', __CLASS__, $sleep));
|
||||
$this->getLogger()->debug(\sprintf('Email transport "%s" sleeps for %d seconds after stopping', __CLASS__, $sleep));
|
||||
|
||||
sleep($sleep);
|
||||
}
|
||||
|
||||
@@ -37,9 +37,9 @@ abstract class AbstractStream
|
||||
public function write(string $bytes, bool $debug = true): void
|
||||
{
|
||||
if ($debug) {
|
||||
$timestamp = date('c');
|
||||
$timestamp = (new \DateTimeImmutable())->format('Y-m-d\TH:i:s.up');
|
||||
foreach (explode("\n", trim($bytes)) as $line) {
|
||||
$this->debug .= sprintf("[%s] > %s\n", $timestamp, $line);
|
||||
$this->debug .= \sprintf("[%s] > %s\n", $timestamp, $line);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,17 +83,17 @@ abstract class AbstractStream
|
||||
if ('' === $line || false === $line) {
|
||||
$metas = stream_get_meta_data($this->out);
|
||||
if ($metas['timed_out']) {
|
||||
throw new TransportException(sprintf('Connection to "%s" timed out.', $this->getReadConnectionDescription()));
|
||||
throw new TransportException(\sprintf('Connection to "%s" timed out.', $this->getReadConnectionDescription()));
|
||||
}
|
||||
if ($metas['eof']) {
|
||||
throw new TransportException(sprintf('Connection to "%s" has been closed unexpectedly.', $this->getReadConnectionDescription()));
|
||||
throw new TransportException(\sprintf('Connection to "%s" has been closed unexpectedly.', $this->getReadConnectionDescription()));
|
||||
}
|
||||
if (false === $line) {
|
||||
throw new TransportException(sprintf('Unable to read from connection to "%s": ', $this->getReadConnectionDescription()).error_get_last()['message']);
|
||||
throw new TransportException(\sprintf('Unable to read from connection to "%s": ', $this->getReadConnectionDescription()).error_get_last()['message']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->debug .= sprintf('[%s] < %s', date('c'), $line);
|
||||
$this->debug .= \sprintf('[%s] < %s', (new \DateTimeImmutable())->format('Y-m-d\TH:i:s.up'), $line);
|
||||
|
||||
return $line;
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ final class SocketStream extends AbstractStream
|
||||
|
||||
$timeout = $this->getTimeout();
|
||||
set_error_handler(function ($type, $msg) {
|
||||
throw new TransportException(sprintf('Connection could not be established with host "%s": ', $this->url).$msg);
|
||||
throw new TransportException(\sprintf('Connection could not be established with host "%s": ', $this->url).$msg);
|
||||
});
|
||||
try {
|
||||
$this->stream = stream_socket_client($this->url, $errno, $errstr, $timeout, \STREAM_CLIENT_CONNECT, $streamContext);
|
||||
|
||||
Reference in New Issue
Block a user