From 7dad4722552dea79668bbae39fed65ba4179fd5d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim=20D=C3=BCsterhus?= Date: Sun, 21 Jun 2015 20:53:46 +0200 Subject: [PATCH] Fix handling of failed connects / logins in SmtpEmailTransport --- .../transport/SmtpEmailTransport.class.php | 80 +++++++++++++------ 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/wcfsetup/install/files/lib/system/email/transport/SmtpEmailTransport.class.php b/wcfsetup/install/files/lib/system/email/transport/SmtpEmailTransport.class.php index 9668b86525..a92427e6dc 100644 --- a/wcfsetup/install/files/lib/system/email/transport/SmtpEmailTransport.class.php +++ b/wcfsetup/install/files/lib/system/email/transport/SmtpEmailTransport.class.php @@ -67,6 +67,13 @@ class SmtpEmailTransport implements EmailTransport { */ protected $features = [ ]; + /** + * if this property is an instance of \Exception email delivery will be locked + * and the \Exception will be thrown when attempting to deliver() an email + * @var \Exception + */ + protected $locked = null; + /** * Creates a new SmtpEmailTransport using the given host. * @@ -234,34 +241,41 @@ class SmtpEmailTransport implements EmailTransport { if ($parameters[0] == 'auth') { // try mechanisms in order of preference foreach ([ 'login', 'plain' ] as $method) { - try { - if (in_array($method, $parameters)) { - switch ($method) { - case 'login': + if (in_array($method, $parameters)) { + switch ($method) { + case 'login': + try { $this->write('AUTH LOGIN'); $this->read([ 334 ]); - $this->write(base64_encode($this->username)); - $this->lastWrite = '*redacted*'; - $this->read([ 334 ]); - $this->write(base64_encode($this->password)); - $this->lastWrite = '*redacted*'; - $this->read([ 235 ]); - return; - break; - case 'plain': - // RFC 4616 + } + catch (SystemException $e) { + // try next authentication method + continue 2; + } + $this->write(base64_encode($this->username)); + $this->lastWrite = '*redacted*'; + $this->read([ 334 ]); + $this->write(base64_encode($this->password)); + $this->lastWrite = '*redacted*'; + $this->read([ 235 ]); + return; + break; + case 'plain': + // RFC 4616 + try { $this->write('AUTH PLAIN'); $this->read([ 334 ]); - $this->write(base64_encode("\0".$this->username."\0".$this->password)); - $this->lastWrite = '*redacted*'; - $this->read([ 235 ]); - return; - } + } + catch (SystemException $e) { + // try next authentication method + continue 2; + } + $this->write(base64_encode("\0".$this->username."\0".$this->password)); + $this->lastWrite = '*redacted*'; + $this->read([ 235 ]); + return; } } - catch (SystemException $e) { - // try next authentication method - } } return; @@ -296,10 +310,28 @@ class SmtpEmailTransport implements EmailTransport { * @param \wcf\system\email\Mailbox $envelopeTo */ public function deliver(Email $email, Mailbox $envelopeTo) { + // delivery is locked + if ($this->locked instanceof \Exception) { + throw $this->locked; + } + if (!$this->connection || $this->connection->eof()) { - $this->connect(); - $this->auth(); + try { + $this->connect(); + $this->auth(); + } + catch (PermanentFailure $e) { + // lock delivery on permanent failure to avoid spamming the SMTP server + $this->locked = $e; + $this->disconnect(); + throw $e; + } + catch (SystemException $e) { + $this->disconnect(); + throw $e; + } } + $this->write('RSET'); $this->read([ 250 ]); $this->write('MAIL FROM:<'.$email->getSender()->getAddress().'>'); -- 2.20.1