refactor: use custom imap client

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-05-08 00:16:43 -04:00
parent a728aeb11c
commit a8764747fd
179 changed files with 6782 additions and 5907 deletions

View File

@@ -0,0 +1,124 @@
<?php
declare(strict_types=1);
namespace KTXM\ProviderImap\Client\Command;
use KTXM\ProviderImap\Client\ImapException;
use KTXM\ProviderImap\Client\Mailbox;
use KTXM\ProviderImap\Client\Protocol\RequestFrame;
use KTXM\ProviderImap\Client\Protocol\Response\TaggedResponse;
use KTXM\ProviderImap\Client\Protocol\Response\UntaggedResponse;
use KTXM\ProviderImap\Client\Protocol\ResponseStream;
use KTXM\ProviderImap\Client\SessionContext;
use KTXM\ProviderImap\Client\SessionState;
/**
* @implements CommandInterface<Mailbox>
*/
final class SelectCommand implements CommandInterface
{
public function __construct(
private readonly string $mailbox,
private readonly bool $readOnly = true,
) {}
public function name(): string
{
return $this->readOnly ? 'EXAMINE' : 'SELECT';
}
public function allowedStates(): array
{
return [
SessionState::Authenticated,
SessionState::Selected,
];
}
public function encode(string $tag, SessionContext $context): RequestFrame
{
unset($tag, $context);
return new RequestFrame(sprintf(
'%s %s',
$this->name(),
$this->quote($this->mailbox),
));
}
public function handle(ResponseStream $responses, SessionContext $context): Mailbox
{
$exists = 0;
$recent = 0;
$flags = [];
$readOnly = $this->readOnly;
foreach ($responses as $response) {
if ($response instanceof UntaggedResponse) {
$raw = $response->raw();
if (preg_match('/^\*\s+(\d+)\s+EXISTS$/i', $raw, $matches)) {
$exists = (int) $matches[1];
continue;
}
if (preg_match('/^\*\s+(\d+)\s+RECENT$/i', $raw, $matches)) {
$recent = (int) $matches[1];
continue;
}
if ($response->label() === 'FLAGS' && preg_match('/\(([^)]*)\)/', $response->payload(), $matches)) {
$flags = $this->parseFlags($matches[1]);
continue;
}
}
if ($response instanceof TaggedResponse) {
if (!$response->isOk()) {
throw new ImapException($this->name() . ' failed: ' . $response->text());
}
if (str_contains(strtoupper($response->text()), 'READ-ONLY')) {
$readOnly = true;
}
$context->setSelectedMailbox($this->mailbox);
$context->setState(SessionState::Selected);
return new Mailbox(
$this->mailbox,
null,
[],
$exists,
0,
null,
$recent,
$flags,
$readOnly,
);
}
}
throw new ImapException($this->name() . ' did not receive a tagged completion response.');
}
/**
* @return list<string>
*/
private function parseFlags(string $flags): array
{
$flags = trim($flags);
if ($flags === '') {
return [];
}
return preg_split('/\s+/', $flags) ?: [];
}
private function quote(string $value): string
{
return '"' . addcslashes($value, "\\\"") . '"';
}
}