connectionFactory->create($config, $this->logger); $connection->connect($config); $reader = new ProtocolReader($connection, $this->logger); $writer = new ProtocolWriter($connection, $this->logger); $session = new SessionContext($config, $connection); $greeting = $reader->readGreeting(); $session->setGreeting($greeting); $session->setState(match ($greeting->status()) { 'OK' => SessionState::NotAuthenticated, 'PREAUTH' => SessionState::Authenticated, 'BYE' => SessionState::Logout, default => throw new ImapException('Unexpected IMAP greeting status: ' . $greeting->status()), }); if ($session->state() === SessionState::Logout) { throw new ImapException('IMAP server rejected the connection: ' . $greeting->text()); } $this->session = $session; $this->executor = new CommandExecutor($reader, $writer, new TagGenerator(), $this->logger); $this->perform(new CapabilityCommand()); if ($config->security() === ConnectionSecurity::StartTls) { $this->perform(new StartTlsCommand()); $this->perform(new CapabilityCommand()); } if ($config->hasCredentials()) { $this->perform(new LoginCommand( $config->username() ?? '', $config->password() ?? '', )); $this->perform(new CapabilityCommand()); } } public function capabilities(): array { return $this->session()->capabilities(); } public function hasCapability(string $capability): bool { return $this->session()->hasCapability($capability); } public function perform(CommandInterface $command): mixed { if ($this->session === null || $this->executor === null) { throw new ImapException('IMAP client is not connected.'); } return $this->executor->perform($command, $this->session); } public function download(FetchTarget $target, string $section, int $chunkSize = 8192): \Generator { if ($this->session === null || $this->executor === null) { throw new ImapException('IMAP client is not connected.'); } return $this->executor->download($target, $section, $chunkSize, $this->session); } public function session(): SessionContext { if ($this->session === null) { throw new ImapException('IMAP client is not connected.'); } return $this->session; } }