blob: d9f2bb68b9e66a069acf53f9a9bb983387b20d85 [file] [log] [blame]
<?php
declare(strict_types=1);
namespace Ddeboer\Imap;
use Ddeboer\Imap\Exception\CreateMailboxException;
use Ddeboer\Imap\Exception\DeleteMailboxException;
use Ddeboer\Imap\Exception\ImapGetmailboxesException;
use Ddeboer\Imap\Exception\ImapNumMsgException;
use Ddeboer\Imap\Exception\ImapQuotaException;
use Ddeboer\Imap\Exception\MailboxDoesNotExistException;
/**
* A connection to an IMAP server that is authenticated for a user.
*/
final class Connection implements ConnectionInterface
{
private ImapResourceInterface $resource;
private string $server;
/**
* @var null|MailboxInterface[]
*/
private ?array $mailboxes = null;
/**
* @var null|array<int|string, \stdClass>
*/
private ?array $mailboxNames = null;
/**
* Constructor.
*
* @throws \InvalidArgumentException
*/
public function __construct(ImapResourceInterface $resource, string $server)
{
$this->resource = $resource;
$this->server = $server;
}
public function getResource(): ImapResourceInterface
{
return $this->resource;
}
public function expunge(): bool
{
return \imap_expunge($this->resource->getStream());
}
public function close(int $flag = 0): bool
{
$this->resource->clearLastMailboxUsedCache();
return \imap_close($this->resource->getStream(), $flag);
}
public function getQuota(string $root = 'INBOX'): array
{
$errorMessage = null;
$errorNumber = 0;
\set_error_handler(static function ($nr, $message) use (&$errorMessage, &$errorNumber): bool {
$errorMessage = $message;
$errorNumber = $nr;
return true;
});
$return = \imap_get_quotaroot($this->resource->getStream(), $root);
\restore_error_handler();
if (false === $return || null !== $errorMessage) {
throw new ImapQuotaException(
\sprintf(
'IMAP Quota request failed for "%s"%s',
$root,
null !== $errorMessage ? ': ' . $errorMessage : ''
),
$errorNumber
);
}
return $return;
}
public function getMailboxes(): array
{
$this->initMailboxNames();
\assert(null !== $this->mailboxNames);
if (null === $this->mailboxes) {
$this->mailboxes = [];
foreach ($this->mailboxNames as $mailboxName => $mailboxInfo) {
$this->mailboxes[(string) $mailboxName] = $this->getMailbox((string) $mailboxName);
}
}
return $this->mailboxes;
}
public function hasMailbox(string $name): bool
{
$this->initMailboxNames();
\assert(null !== $this->mailboxNames);
return isset($this->mailboxNames[$name]);
}
public function getMailbox(string $name): MailboxInterface
{
if (false === $this->hasMailbox($name)) {
throw new MailboxDoesNotExistException(\sprintf('Mailbox name "%s" does not exist', $name));
}
\assert(isset($this->mailboxNames[$name]));
return new Mailbox($this->resource, $name, $this->mailboxNames[$name]);
}
public function count()
{
$return = \imap_num_msg($this->resource->getStream());
if (false === $return) {
throw new ImapNumMsgException('imap_num_msg failed');
}
return $return;
}
public function ping(): bool
{
return \imap_ping($this->resource->getStream());
}
public function createMailbox(string $name): MailboxInterface
{
if (false === \imap_createmailbox($this->resource->getStream(), $this->server . \mb_convert_encoding($name, 'UTF7-IMAP', 'UTF-8'))) {
throw new CreateMailboxException(\sprintf('Can not create "%s" mailbox at "%s"', $name, $this->server));
}
$this->mailboxNames = $this->mailboxes = null;
$this->resource->clearLastMailboxUsedCache();
return $this->getMailbox($name);
}
public function deleteMailbox(MailboxInterface $mailbox): void
{
if (false === \imap_deletemailbox($this->resource->getStream(), $mailbox->getFullEncodedName())) {
throw new DeleteMailboxException(\sprintf('Mailbox "%s" could not be deleted', $mailbox->getName()));
}
$this->mailboxes = $this->mailboxNames = null;
$this->resource->clearLastMailboxUsedCache();
}
private function initMailboxNames(): void
{
if (null !== $this->mailboxNames) {
return;
}
$this->mailboxNames = [];
$mailboxesInfo = \imap_getmailboxes($this->resource->getStream(), $this->server, '*');
if (!\is_array($mailboxesInfo)) {
throw new ImapGetmailboxesException('imap_getmailboxes failed');
}
foreach ($mailboxesInfo as $mailboxInfo) {
$name = \mb_convert_encoding(\str_replace($this->server, '', $mailboxInfo->name), 'UTF-8', 'UTF7-IMAP');
\assert(\is_string($name));
$this->mailboxNames[$name] = $mailboxInfo;
}
}
}