generated from Nodarx/template
refactor: use custom imap client
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
121
lib/Client/Protocol/ProtocolReader.php
Normal file
121
lib/Client/Protocol/ProtocolReader.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KTXM\ProviderImap\Client\Protocol;
|
||||
|
||||
use KTXM\ProviderImap\Client\ImapException;
|
||||
use KTXM\ProviderImap\Client\Protocol\Response\ContinuationResponse;
|
||||
use KTXM\ProviderImap\Client\Protocol\Response\GreetingResponse;
|
||||
use KTXM\ProviderImap\Client\Protocol\Response\ResponseInterface;
|
||||
use KTXM\ProviderImap\Client\Protocol\Response\TaggedResponse;
|
||||
use KTXM\ProviderImap\Client\Protocol\Response\UntaggedResponse;
|
||||
use KTXM\ProviderImap\Client\Transport\ConnectionInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
final class ProtocolReader
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ConnectionInterface $connection,
|
||||
private readonly ?LoggerInterface $logger = null,
|
||||
) {}
|
||||
|
||||
public function readGreeting(): GreetingResponse
|
||||
{
|
||||
$raw = $this->trimTrailingLineEnding($this->connection->readLine());
|
||||
|
||||
if (!str_starts_with($raw, '* ')) {
|
||||
throw new ImapException(sprintf('Expected IMAP greeting, got: %s', $raw));
|
||||
}
|
||||
|
||||
$parts = preg_split('/\s+/', substr($raw, 2), 2) ?: [];
|
||||
$status = strtoupper($parts[0] ?? '');
|
||||
$text = $parts[1] ?? '';
|
||||
|
||||
$this->logger?->debug('IMAP greeting received: {raw}', [
|
||||
'status' => $status,
|
||||
'raw' => $raw,
|
||||
]);
|
||||
|
||||
return new GreetingResponse($status, $text, $raw);
|
||||
}
|
||||
|
||||
public function readResponse(): ResponseInterface
|
||||
{
|
||||
$raw = $this->readRawResponse();
|
||||
|
||||
if ($raw === '') {
|
||||
throw new ImapException('Received empty IMAP response line.');
|
||||
}
|
||||
|
||||
if (str_starts_with($raw, '* ')) {
|
||||
$parts = preg_split('/\s+/', substr($raw, 2), 2) ?: [];
|
||||
$label = strtoupper($parts[0] ?? '');
|
||||
$this->logger?->debug('IMAP untagged response received: {raw}', [
|
||||
'label' => $label,
|
||||
'raw' => $raw,
|
||||
]);
|
||||
return new UntaggedResponse(
|
||||
$label,
|
||||
$parts[1] ?? '',
|
||||
$raw,
|
||||
);
|
||||
}
|
||||
|
||||
if (str_starts_with($raw, '+')) {
|
||||
$this->logger?->debug('IMAP continuation response received: {raw}', [
|
||||
'raw' => $raw,
|
||||
]);
|
||||
return new ContinuationResponse(ltrim(substr($raw, 1)), $raw);
|
||||
}
|
||||
|
||||
$parts = preg_split('/\s+/', $raw, 3) ?: [];
|
||||
|
||||
if (count($parts) < 2) {
|
||||
throw new ImapException(sprintf('Malformed tagged IMAP response: %s', $raw));
|
||||
}
|
||||
|
||||
$status = strtoupper($parts[1]);
|
||||
$this->logger?->debug('IMAP tagged response received: {raw}', [
|
||||
'tag' => $parts[0],
|
||||
'status' => $status,
|
||||
'raw' => $raw,
|
||||
]);
|
||||
|
||||
return new TaggedResponse($parts[0], $status, $parts[2] ?? '', $raw);
|
||||
}
|
||||
|
||||
private function readRawResponse(): string
|
||||
{
|
||||
$raw = $this->connection->readLine();
|
||||
|
||||
while (($literalLength = $this->trailingLiteralLength($raw)) !== null) {
|
||||
$raw .= $this->connection->readBytes($literalLength);
|
||||
$raw .= $this->connection->readLine();
|
||||
}
|
||||
|
||||
return $this->trimTrailingLineEnding($raw);
|
||||
}
|
||||
|
||||
private function trailingLiteralLength(string $raw): ?int
|
||||
{
|
||||
if (preg_match('/\{(\d+)\}\r?\n$/', $raw, $matches) !== 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (int) $matches[1];
|
||||
}
|
||||
|
||||
private function trimTrailingLineEnding(string $raw): string
|
||||
{
|
||||
if (str_ends_with($raw, "\r\n")) {
|
||||
return substr($raw, 0, -2);
|
||||
}
|
||||
|
||||
if (str_ends_with($raw, "\n")) {
|
||||
return substr($raw, 0, -1);
|
||||
}
|
||||
|
||||
return $raw;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user