Skip to content

Commit

Permalink
fix(smtp): support RSET; better mailing workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
roxblnfk committed Jan 19, 2025
1 parent c022a54 commit a6088ab
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 7 deletions.
17 changes: 13 additions & 4 deletions src/Traffic/Dispatcher/Smtp.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,18 @@ public function __construct(
$this->parser = new Parser\Smtp();
}

// todo support Auth https://www.rfc-editor.org/rfc/rfc4954
public function dispatch(StreamClient $stream): iterable
{
$stream->sendData($this->createResponse(self::READY, 'mailamie'));
$protocol = [];
$message = null;
while (!$stream->isFinished()) {
$response = $stream->fetchLine();
if (\preg_match('/^(?:EHLO|HELO)/', $response)) {
$response = \ltrim($stream->fetchLine(), ' ');
if (\str_starts_with($response, 'NOOP')) {
$stream->sendData($this->createResponse(self::OK));
} elseif (\preg_match('/^(?:EHLO|HELO|RSET)/', $response)) {
$stream->sendData($this->createResponse(self::OK));
$protocol = [];
} elseif (\preg_match('/^MAIL FROM:\s*<(.*)>/', $response, $matches)) {
/** @var array{0: non-empty-string, 1: string} $matches */
$protocol['FROM'][] = $matches[1];
Expand All @@ -46,12 +49,18 @@ public function dispatch(StreamClient $stream): iterable
$stream->sendData($this->createResponse(self::OK));
} elseif (\str_starts_with($response, 'QUIT')) {
$stream->sendData($this->createResponse(self::CLOSING));
yield new Frame\Smtp($message, $stream->getCreatedAt());
$stream->disconnect();
return;
} elseif (\str_starts_with($response, 'RSET')) {
$stream->sendData($this->createResponse(self::OK));
$protocol = [];
} elseif (\str_starts_with($response, 'DATA')) {
$stream->sendData($this->createResponse(self::START_MAIL_INPUT));
$message = $this->parser->parseStream($protocol, $stream);
$stream->sendData($this->createResponse(self::OK));
yield new Frame\Smtp($message, $stream->getCreatedAt());
$protocol = [];
unset($message);
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions tests/Unit/Traffic/Dispatcher/SmtpTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SmtpTest extends TestCase

public function testDispatchOneMail(): void
{
$stream = StreamClientMock::createFromGenerator($this->mailMe());
$stream = StreamClientMock::createFromGenerator($this->mailMe(quit: true));

$this->runInFiber(static function () use ($stream) {
foreach ((new Smtp())->dispatch($stream) as $frame) {
Expand Down Expand Up @@ -58,7 +58,7 @@ public function testDispatchMultipleMails(): void
});
}

private function mailMe(string $subject = 'Test email'): \Generator
private function mailMe(string $subject = 'Test email', bool $quit = false): \Generator
{
yield "EHLO\r\n";
yield "MAIL FROM: <[email protected]>\r\n";
Expand All @@ -72,6 +72,8 @@ private function mailMe(string $subject = 'Test email'): \Generator
yield "\r\n";
yield "Hello, this is a test email.\r\n";
yield ".\r\n";
yield "QUIT\r\n";
if ($quit) {
yield "QUIT\r\n";
}
}
}

0 comments on commit a6088ab

Please sign in to comment.