127 lines
3.5 KiB
PHP
127 lines
3.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Ddeboer\Imap;
|
|
|
|
use Ddeboer\Imap\Exception\AuthenticationFailedException;
|
|
use Ddeboer\Imap\Exception\ResourceCheckFailureException;
|
|
|
|
/**
|
|
* An IMAP server.
|
|
*/
|
|
final class Server implements ServerInterface
|
|
{
|
|
private string $hostname;
|
|
private string $port;
|
|
private string $flags;
|
|
/**
|
|
* @var mixed[]
|
|
*/
|
|
private array $parameters;
|
|
private int $options;
|
|
private int $retries;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param string $hostname Internet domain name or bracketed IP address
|
|
* of server
|
|
* @param string $port TCP port number
|
|
* @param string $flags Optional flags
|
|
* @param mixed[] $parameters Connection parameters
|
|
* @param int $options Connection options
|
|
* @param int $retries Retries number
|
|
*/
|
|
public function __construct(
|
|
string $hostname,
|
|
string $port = '993',
|
|
string $flags = '/imap/ssl/validate-cert',
|
|
array $parameters = [],
|
|
int $options = 0,
|
|
int $retries = 1
|
|
) {
|
|
if (!\function_exists('imap_open')) {
|
|
throw new \RuntimeException('IMAP extension must be enabled');
|
|
}
|
|
|
|
$this->hostname = $hostname;
|
|
$this->port = $port;
|
|
$this->flags = '' !== $flags ? '/' . \ltrim($flags, '/') : '';
|
|
$this->parameters = $parameters;
|
|
$this->options = $options;
|
|
$this->retries = $retries;
|
|
}
|
|
|
|
/**
|
|
* Authenticate connection.
|
|
*
|
|
* @param string $username Username
|
|
* @param string $password Password
|
|
*
|
|
* @throws AuthenticationFailedException
|
|
*/
|
|
public function authenticate(string $username, string $password): ConnectionInterface
|
|
{
|
|
$errorMessage = null;
|
|
$errorNumber = 0;
|
|
\set_error_handler(static function ($nr, $message) use (&$errorMessage, &$errorNumber): bool {
|
|
$errorMessage = $message;
|
|
$errorNumber = $nr;
|
|
|
|
return true;
|
|
});
|
|
|
|
$resource = \imap_open(
|
|
$this->getServerString(),
|
|
$username,
|
|
$password,
|
|
$this->options,
|
|
$this->retries,
|
|
$this->parameters
|
|
);
|
|
|
|
\restore_error_handler();
|
|
|
|
if (false === $resource || null !== $errorMessage) {
|
|
throw new AuthenticationFailedException(\sprintf(
|
|
'Authentication failed for user "%s"%s',
|
|
$username,
|
|
null !== $errorMessage ? ': ' . $errorMessage : ''
|
|
), $errorNumber);
|
|
}
|
|
|
|
$check = \imap_check($resource);
|
|
|
|
if (false === $check) {
|
|
throw new ResourceCheckFailureException('Resource check failure');
|
|
}
|
|
|
|
$mailbox = $check->Mailbox;
|
|
$connection = $mailbox;
|
|
$curlyPosition = \strpos($mailbox, '}');
|
|
if (false !== $curlyPosition) {
|
|
$connection = \substr($mailbox, 0, $curlyPosition + 1);
|
|
}
|
|
|
|
// These are necessary to get rid of PHP throwing IMAP errors
|
|
\imap_errors();
|
|
\imap_alerts();
|
|
|
|
return new Connection(new ImapResource($resource), $connection);
|
|
}
|
|
|
|
/**
|
|
* Glues hostname, port and flags and returns result.
|
|
*/
|
|
private function getServerString(): string
|
|
{
|
|
return \sprintf(
|
|
'{%s%s%s}',
|
|
$this->hostname,
|
|
'' !== $this->port ? ':' . $this->port : '',
|
|
$this->flags
|
|
);
|
|
}
|
|
}
|