ALPHA 3.0.2a

This commit is contained in:
TheGamecraft
2018-09-10 08:51:18 -04:00
parent 7fe13ae0a7
commit 0e0ef86b71
1404 changed files with 10604 additions and 33714 deletions

View File

@@ -1,6 +1,11 @@
Changelog
=========
6.1.2 (2018-07-13)
------------------
* handled recipient errors when pipelining
6.1.1 (2018-07-04)
------------------

View File

@@ -15,7 +15,7 @@
*/
abstract class Swift
{
const VERSION = '6.1.1';
const VERSION = '6.1.2';
public static $initialized = false;
public static $inits = [];

View File

@@ -313,15 +313,18 @@ abstract class Swift_Transport_AbstractSmtpTransport implements Swift_Transport
*
* If no response codes are given, the response will not be validated.
* If codes are given, an exception will be thrown on an invalid response.
* If the command is RCPT TO, and the pipeline is non-empty, no exception
* will be thrown; instead the failing address is added to $failures.
*
* @param string $command
* @param int[] $codes
* @param string[] $failures An array of failures by-reference
* @param bool $pipeline Do not wait for response
* @param string $address The address, if command is RCPT TO.
*
* @return string|null The server response, or null if pipelining is enabled
*/
public function executeCommand($command, $codes = [], &$failures = null, $pipeline = false)
public function executeCommand($command, $codes = [], &$failures = null, $pipeline = false, $address = null)
{
$failures = (array) $failures;
$seq = $this->buffer->write($command);
@@ -329,14 +332,22 @@ abstract class Swift_Transport_AbstractSmtpTransport implements Swift_Transport
$this->eventDispatcher->dispatchEvent($evt, 'commandSent');
}
$this->pipeline[] = [$command, $seq, $codes];
$this->pipeline[] = [$command, $seq, $codes, $address];
if ($pipeline && $this->pipelining) {
$response = null;
} else {
while ($this->pipeline) {
list($command, $seq, $codes) = array_shift($this->pipeline);
list($command, $seq, $codes, $address) = array_shift($this->pipeline);
$response = $this->getFullResponse($seq);
$this->assertResponseCode($response, $codes);
try {
$this->assertResponseCode($response, $codes);
} catch (Swift_TransportException $e) {
if ($this->pipeline && $address) {
$failures[] = $address;
} else {
$this->throwException($e);
}
}
}
}
@@ -371,14 +382,14 @@ abstract class Swift_Transport_AbstractSmtpTransport implements Swift_Transport
{
$address = $this->addressEncoder->encodeString($address);
$this->executeCommand(
sprintf("RCPT TO:<%s>\r\n", $address), [250, 251, 252], $failures, true
sprintf("RCPT TO:<%s>\r\n", $address), [250, 251, 252], $failures, true, $address
);
}
/** Send the DATA command */
protected function doDataCommand()
protected function doDataCommand(&$failedRecipients)
{
$this->executeCommand("DATA\r\n", [354]);
$this->executeCommand("DATA\r\n", [354], $failedRecipients);
}
/** Stream the contents of the message over the buffer */
@@ -488,7 +499,10 @@ abstract class Swift_Transport_AbstractSmtpTransport implements Swift_Transport
}
if (0 != $sent) {
$this->doDataCommand();
$sent += count($failedRecipients);
$this->doDataCommand($failedRecipients);
$sent -= count($failedRecipients);
$this->streamMessage($message);
} else {
$this->reset();

View File

@@ -284,10 +284,11 @@ class Swift_Transport_EsmtpTransport extends Swift_Transport_AbstractSmtpTranspo
* @param int[] $codes
* @param string[] $failures An array of failures by-reference
* @param bool $pipeline Do not wait for response
* @param string $address The address, if command is RCPT TO.
*
* @return string
* @return string|null The server response, or null if pipelining is enabled
*/
public function executeCommand($command, $codes = [], &$failures = null, $pipeline = false)
public function executeCommand($command, $codes = [], &$failures = null, $pipeline = false, $address = null)
{
$failures = (array) $failures;
$stopSignal = false;
@@ -301,7 +302,7 @@ class Swift_Transport_EsmtpTransport extends Swift_Transport_AbstractSmtpTranspo
}
}
return parent::executeCommand($command, $codes, $failures, $pipeline);
return parent::executeCommand($command, $codes, $failures, $pipeline, $address);
}
/** Mixin handling method for ESMTP handlers */
@@ -397,7 +398,7 @@ class Swift_Transport_EsmtpTransport extends Swift_Transport_AbstractSmtpTranspo
}
$paramStr = !empty($params) ? ' '.implode(' ', $params) : '';
$this->executeCommand(
sprintf("RCPT TO:<%s>%s\r\n", $address, $paramStr), [250, 251, 252], $failures, true
sprintf("RCPT TO:<%s>%s\r\n", $address, $paramStr), [250, 251, 252], $failures, true, $address
);
}

View File

@@ -278,7 +278,7 @@ class Swift_Transport_EsmtpTransportTest extends Swift_Transport_AbstractSmtpEve
$smtp->start();
}
public function testPipelining2()
public function testPipelining()
{
$buf = $this->getBuffer();
$smtp = $this->getTransport($buf);
@@ -340,11 +340,242 @@ class Swift_Transport_EsmtpTransportTest extends Swift_Transport_AbstractSmtpEve
$this->finishBuffer($buf);
$smtp->start();
$smtp->send($message);
$sent = $smtp->send($message, $failedRecipients);
$this->assertEquals(1, $sent);
$this->assertEmpty($failedRecipients);
$this->assertTrue($smtp->getPipelining());
}
public function testPipeliningWithRecipientFailure()
{
$buf = $this->getBuffer();
$smtp = $this->getTransport($buf);
$this->assertNull($smtp->getPipelining());
$message = $this->createMessage();
$message->shouldReceive('getFrom')
->zeroOrMoreTimes()
->andReturn(['me@domain.com' => 'Me']);
$message->shouldReceive('getTo')
->zeroOrMoreTimes()
->andReturn([
'good@foo' => null,
'bad@foo' => null,
'good@bar' => null,
]);
$buf->shouldReceive('initialize')
->once();
$buf->shouldReceive('readLine')
->once()
->with(0)
->andReturn("220 some.server.tld bleh\r\n");
$buf->shouldReceive('write')
->once()
->with('~^EHLO .+?\r\n$~D')
->andReturn(1);
$buf->shouldReceive('readLine')
->once()
->with(1)
->andReturn('250-ServerName'."\r\n");
$buf->shouldReceive('readLine')
->once()
->with(1)
->andReturn('250 PIPELINING'."\r\n");
$buf->shouldReceive('write')
->ordered()
->once()
->with("MAIL FROM:<me@domain.com>\r\n")
->andReturn(1);
$buf->shouldReceive('write')
->ordered()
->once()
->with("RCPT TO:<good@foo>\r\n")
->andReturn(2);
$buf->shouldReceive('write')
->ordered()
->once()
->with("RCPT TO:<bad@foo>\r\n")
->andReturn(3);
$buf->shouldReceive('write')
->ordered()
->once()
->with("RCPT TO:<good@bar>\r\n")
->andReturn(4);
$buf->shouldReceive('write')
->ordered()
->once()
->with("DATA\r\n")
->andReturn(5);
$buf->shouldReceive('readLine')
->ordered()
->once()
->with(1)
->andReturn("250 OK\r\n");
$buf->shouldReceive('readLine')
->ordered()
->once()
->with(2)
->andReturn("250 OK\r\n");
$buf->shouldReceive('readLine')
->ordered()
->once()
->with(3)
->andReturn("450 Unknown address bad@foo\r\n");
$buf->shouldReceive('readLine')
->ordered()
->once()
->with(4)
->andReturn("250 OK\r\n");
$buf->shouldReceive('readLine')
->ordered()
->once()
->with(5)
->andReturn("354 OK\r\n");
$this->finishBuffer($buf);
$smtp->start();
$sent = $smtp->send($message, $failedRecipients);
$this->assertEquals(2, $sent);
$this->assertEquals(['bad@foo'], $failedRecipients);
$this->assertTrue($smtp->getPipelining());
}
public function testPipeliningWithSenderFailure()
{
$buf = $this->getBuffer();
$smtp = $this->getTransport($buf);
$this->assertNull($smtp->getPipelining());
$message = $this->createMessage();
$message->shouldReceive('getFrom')
->zeroOrMoreTimes()
->andReturn(['me@domain.com' => 'Me']);
$message->shouldReceive('getTo')
->zeroOrMoreTimes()
->andReturn(['foo@bar' => null]);
$buf->shouldReceive('initialize')
->once();
$buf->shouldReceive('readLine')
->once()
->with(0)
->andReturn("220 some.server.tld bleh\r\n");
$buf->shouldReceive('write')
->once()
->with('~^EHLO .+?\r\n$~D')
->andReturn(1);
$buf->shouldReceive('readLine')
->once()
->with(1)
->andReturn('250-ServerName'."\r\n");
$buf->shouldReceive('readLine')
->once()
->with(1)
->andReturn('250 PIPELINING'."\r\n");
$buf->shouldReceive('write')
->ordered()
->once()
->with("MAIL FROM:<me@domain.com>\r\n")
->andReturn(1);
$buf->shouldReceive('write')
->ordered()
->once()
->with("RCPT TO:<foo@bar>\r\n")
->andReturn(2);
$buf->shouldReceive('write')
->ordered()
->once()
->with("DATA\r\n")->andReturn(3);
$buf->shouldReceive('readLine')
->ordered()
->once()
->with(1)
->andReturn("550 Unknown address me@domain.com\r\n");
$smtp->start();
$this->expectException('Swift_TransportException');
$this->expectExceptionMessage('Expected response code 250 but got code "550"');
$smtp->send($message, $failedRecipients);
}
public function testPipeliningWithDataFailure()
{
$buf = $this->getBuffer();
$smtp = $this->getTransport($buf);
$this->assertNull($smtp->getPipelining());
$message = $this->createMessage();
$message->shouldReceive('getFrom')
->zeroOrMoreTimes()
->andReturn(['me@domain.com' => 'Me']);
$message->shouldReceive('getTo')
->zeroOrMoreTimes()
->andReturn(['foo@bar' => null]);
$buf->shouldReceive('initialize')
->once();
$buf->shouldReceive('readLine')
->once()
->with(0)
->andReturn("220 some.server.tld bleh\r\n");
$buf->shouldReceive('write')
->once()
->with('~^EHLO .+?\r\n$~D')
->andReturn(1);
$buf->shouldReceive('readLine')
->once()
->with(1)
->andReturn('250-ServerName'."\r\n");
$buf->shouldReceive('readLine')
->once()
->with(1)
->andReturn('250 PIPELINING'."\r\n");
$buf->shouldReceive('write')
->ordered()
->once()
->with("MAIL FROM:<me@domain.com>\r\n")
->andReturn(1);
$buf->shouldReceive('write')
->ordered()
->once()
->with("RCPT TO:<foo@bar>\r\n")
->andReturn(2);
$buf->shouldReceive('write')
->ordered()
->once()
->with("DATA\r\n")->andReturn(3);
$buf->shouldReceive('readLine')
->ordered()
->once()
->with(1)
->andReturn("250 OK\r\n");
$buf->shouldReceive('readLine')
->ordered()
->once()
->with(2)
->andReturn("250 OK\r\n");
$buf->shouldReceive('readLine')
->ordered()
->once()
->with(3)
->andReturn("452 Insufficient system storage\r\n");
$smtp->start();
$this->expectException('Swift_TransportException');
$this->expectExceptionMessage('Expected response code 354 but got code "452"');
$smtp->send($message, $failedRecipients);
}
public function providerPipeliningOverride()
{
return [