generated from Nodarx/template
ad6b7c5eba
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
69 lines
1.9 KiB
PHP
69 lines
1.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* SPDX-FileCopyrightText: Sebastian Krupinski <krupinski01@gmail.com>
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
namespace KTXM\ProviderImap\Smtp\Protocol;
|
|
|
|
use KTXM\ProviderImap\Smtp\SmtpException;
|
|
use KTXM\ProviderImap\Smtp\Transport\ConnectionInterface;
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
/**
|
|
* Reads SMTP replies, assembling multi-line responses.
|
|
*
|
|
* A multi-line reply repeats the status code on every line, using a hyphen
|
|
* ("250-text") to indicate continuation and a space ("250 text") on the final
|
|
* line. See RFC 5321 §4.2.
|
|
*/
|
|
final class ReplyReader
|
|
{
|
|
public function __construct(
|
|
private readonly ConnectionInterface $connection,
|
|
private readonly ?LoggerInterface $logger = null,
|
|
) {}
|
|
|
|
public function read(): Reply
|
|
{
|
|
$lines = [];
|
|
$raw = '';
|
|
$code = null;
|
|
|
|
while (true) {
|
|
$rawLine = $this->connection->readLine();
|
|
$raw .= $rawLine;
|
|
$trimmed = rtrim($rawLine, "\r\n");
|
|
|
|
if (!preg_match('/^(\d{3})([ -]?)(.*)$/', $trimmed, $matches)) {
|
|
throw new SmtpException(sprintf('Malformed SMTP reply line: %s', $trimmed));
|
|
}
|
|
|
|
$lineCode = (int) $matches[1];
|
|
$separator = $matches[2];
|
|
$lines[] = $matches[3];
|
|
|
|
if ($code === null) {
|
|
$code = $lineCode;
|
|
} elseif ($lineCode !== $code) {
|
|
throw new SmtpException(sprintf('Inconsistent SMTP reply code: %s', $trimmed));
|
|
}
|
|
|
|
// A space separator (or no separator) marks the final line.
|
|
if ($separator !== '-') {
|
|
break;
|
|
}
|
|
}
|
|
|
|
$this->logger?->debug('SMTP reply received: {raw}', [
|
|
'code' => $code,
|
|
'raw' => rtrim($raw, "\r\n"),
|
|
]);
|
|
|
|
return new Reply($code ?? 0, $lines, rtrim($raw, "\r\n"));
|
|
}
|
|
}
|