[Web] Prepare for oauth2

[Web] Some lib updates
[Web] Allow to add a footer
This commit is contained in:
andryyy
2019-09-28 20:00:04 +02:00
parent 3811866ea0
commit 7a85abdb42
176 changed files with 18448 additions and 504 deletions

View File

@@ -1,5 +1,48 @@
# Change Log
## [1.8.0](https://github.com/ddeboer/imap/tree/1.8.0) (2019-04-15)
[Full Changelog](https://github.com/ddeboer/imap/compare/1.7.2...1.8.0)
**Implemented enhancements:**
- Add phpstan-strict-rules, expose PartiInterface::getDescription\(\) [\#409](https://github.com/ddeboer/imap/pull/409) ([Slamdunk](https://github.com/Slamdunk))
## [1.7.2](https://github.com/ddeboer/imap/tree/1.7.2) (2019-04-12)
[Full Changelog](https://github.com/ddeboer/imap/compare/1.7.1...1.7.2)
**Fixed bugs:**
- Handle message/rfc822 when content-disposition is missing [\#410](https://github.com/ddeboer/imap/pull/410) ([Daredzik](https://github.com/Daredzik))
## [1.7.1](https://github.com/ddeboer/imap/tree/1.7.1) (2019-03-18)
[Full Changelog](https://github.com/ddeboer/imap/compare/1.7.0...1.7.1)
**Fixed bugs:**
- Encoding problem with 1.7 [\#405](https://github.com/ddeboer/imap/issues/405)
- imap\_search/imap\_sort: default params must not be passed if unspecified [\#406](https://github.com/ddeboer/imap/pull/406) ([Slamdunk](https://github.com/Slamdunk))
## [1.7.0](https://github.com/ddeboer/imap/tree/1.7.0) (2019-03-04)
[Full Changelog](https://github.com/ddeboer/imap/compare/1.6.0...1.7.0)
**Implemented enhancements:**
- Docker and Travis differs in handling new message eols [\#404](https://github.com/ddeboer/imap/pull/404) ([Slamdunk](https://github.com/Slamdunk))
- Update PHP-CS-Fixer rules [\#403](https://github.com/ddeboer/imap/pull/403) ([Slamdunk](https://github.com/Slamdunk))
- Add charset for imap\_search or imap\_sort [\#402](https://github.com/ddeboer/imap/pull/402) ([Slamdunk](https://github.com/Slamdunk))
- PHPStan clean ups [\#400](https://github.com/ddeboer/imap/pull/400) ([Slamdunk](https://github.com/Slamdunk))
- Adding an undelete\(\) message method [\#386](https://github.com/ddeboer/imap/pull/386) ([C-Duv](https://github.com/C-Duv))
**Closed issues:**
- Convert from GBK \(X-GBK\) to UTF-8 Issue [\#395](https://github.com/ddeboer/imap/issues/395)
**Merged pull requests:**
- Add new ResourceCheckFailureException to handle imap\_check\(\) false [\#399](https://github.com/ddeboer/imap/pull/399) ([pyatnitsev](https://github.com/pyatnitsev))
- Remove GBK -\> X-GBK Alias and add X-GBK -\> GBK [\#396](https://github.com/ddeboer/imap/pull/396) ([pyatnitsev](https://github.com/pyatnitsev))
- Add Feature Requests to README.md [\#394](https://github.com/ddeboer/imap/pull/394) ([Slamdunk](https://github.com/Slamdunk))
## [1.6.0](https://github.com/ddeboer/imap/tree/1.6.0) (2018-12-04)
[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.5...1.6.0)

View File

@@ -14,6 +14,7 @@ This library requires [IMAP](https://secure.php.net/manual/en/book.imap.php),
## Table of Contents
1. [Feature Requests](#feature-requests)
1. [Installation](#installation)
1. [Usage](#usage)
1. [Connect and Authenticate](#connect-and-authenticate)
@@ -29,6 +30,10 @@ This library requires [IMAP](https://secure.php.net/manual/en/book.imap.php),
1. [Running the Tests](#running-the-tests)
1. [Running Tests using Docker](#running-tests-using-docker)
## Feature Requests
[![Feature Requests](https://feathub.com/ddeboer/imap?format=svg)](https://feathub.com/ddeboer/imap)
## Installation
The recommended way to install the IMAP library is through [Composer](https://getcomposer.org):

View File

@@ -28,10 +28,11 @@
"ext-mbstring": "*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.13",
"phpstan/phpstan": "^0.9.1",
"phpstan/phpstan-phpunit": "^0.9.3",
"phpunit/phpunit": "^7.4",
"friendsofphp/php-cs-fixer": "^2.14",
"phpstan/phpstan": "^0.11",
"phpstan/phpstan-phpunit": "^0.11",
"phpstan/phpstan-strict-rules": "^0.11.0",
"phpunit/phpunit": "^7.5",
"zendframework/zend-mail": "^2.10"
},
"autoload": {

View File

@@ -7,6 +7,7 @@ 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\InvalidResourceException;
use Ddeboer\Imap\Exception\MailboxDoesNotExistException;
@@ -46,7 +47,7 @@ final class Connection implements ConnectionInterface
public function __construct(ImapResourceInterface $resource, string $server)
{
$this->resource = $resource;
$this->server = $server;
$this->server = $server;
}
/**
@@ -139,7 +140,13 @@ final class Connection implements ConnectionInterface
*/
public function count()
{
return \imap_num_msg($this->resource->getStream());
$return = \imap_num_msg($this->resource->getStream());
if (false === $return) {
throw new ImapNumMsgException('imap_num_msg failed');
}
return $return;
}
/**
@@ -202,13 +209,13 @@ final class Connection implements ConnectionInterface
}
$this->mailboxNames = [];
$mailboxesInfo = \imap_getmailboxes($this->resource->getStream(), $this->server, '*');
$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');
$name = \mb_convert_encoding(\str_replace($this->server, '', $mailboxInfo->name), 'UTF-8', 'UTF7-IMAP');
$this->mailboxNames[$name] = $mailboxInfo;
}
}

View File

@@ -10,21 +10,21 @@ abstract class AbstractException extends \RuntimeException
* @var array
*/
private static $errorLabels = [
\E_ERROR => 'E_ERROR',
\E_WARNING => 'E_WARNING',
\E_PARSE => 'E_PARSE',
\E_NOTICE => 'E_NOTICE',
\E_CORE_ERROR => 'E_CORE_ERROR',
\E_CORE_WARNING => 'E_CORE_WARNING',
\E_COMPILE_ERROR => 'E_COMPILE_ERROR',
\E_COMPILE_WARNING => 'E_COMPILE_WARNING',
\E_USER_ERROR => 'E_USER_ERROR',
\E_USER_WARNING => 'E_USER_WARNING',
\E_USER_NOTICE => 'E_USER_NOTICE',
\E_STRICT => 'E_STRICT',
\E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
\E_DEPRECATED => 'E_DEPRECATED',
\E_USER_DEPRECATED => 'E_USER_DEPRECATED',
\E_ERROR => 'E_ERROR',
\E_WARNING => 'E_WARNING',
\E_PARSE => 'E_PARSE',
\E_NOTICE => 'E_NOTICE',
\E_CORE_ERROR => 'E_CORE_ERROR',
\E_CORE_WARNING => 'E_CORE_WARNING',
\E_COMPILE_ERROR => 'E_COMPILE_ERROR',
\E_COMPILE_WARNING => 'E_COMPILE_WARNING',
\E_USER_ERROR => 'E_USER_ERROR',
\E_USER_WARNING => 'E_USER_WARNING',
\E_USER_NOTICE => 'E_USER_NOTICE',
\E_STRICT => 'E_STRICT',
\E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
\E_DEPRECATED => 'E_DEPRECATED',
\E_USER_DEPRECATED => 'E_USER_DEPRECATED',
];
/**
@@ -35,21 +35,21 @@ abstract class AbstractException extends \RuntimeException
final public function __construct(string $message, int $code = 0, \Throwable $previous = null)
{
$errorType = '';
if (\is_int($code) && isset(self::$errorLabels[$code])) {
if (isset(self::$errorLabels[$code])) {
$errorType = \sprintf('[%s] ', self::$errorLabels[$code]);
}
$joinString = "\n- ";
$alerts = \imap_alerts();
$errors = \imap_errors();
$joinString = "\n- ";
$alerts = \imap_alerts();
$errors = \imap_errors();
$completeMessage = \sprintf(
"%s%s\nimap_alerts (%s):%s\nimap_errors (%s):%s",
$errorType,
$message,
$alerts ? \count($alerts) : 0,
$alerts ? $joinString . \implode($joinString, $alerts) : '',
$errors ? \count($errors) : 0,
$errors ? $joinString . \implode($joinString, $errors) : ''
false !== $alerts ? \count($alerts) : 0,
false !== $alerts ? $joinString . \implode($joinString, $alerts) : '',
false !== $errors ? \count($errors) : 0,
false !== $errors ? $joinString . \implode($joinString, $errors) : ''
);
parent::__construct($completeMessage, $code, $previous);

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Ddeboer\Imap\Exception;
final class ImapFetchbodyException extends AbstractException
{
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Ddeboer\Imap\Exception;
final class ImapFetchheaderException extends AbstractException
{
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Ddeboer\Imap\Exception;
final class ImapMsgnoException extends AbstractException
{
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Ddeboer\Imap\Exception;
final class ImapNumMsgException extends AbstractException
{
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Ddeboer\Imap\Exception;
final class ImapStatusException extends AbstractException
{
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Ddeboer\Imap\Exception;
final class MessageUndeleteException extends AbstractException
{
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Ddeboer\Imap\Exception;
final class ResourceCheckFailureException extends AbstractException
{
}

View File

@@ -13,7 +13,7 @@ use Ddeboer\Imap\Exception\ReopenMailboxException;
final class ImapResource implements ImapResourceInterface
{
/**
* @var resource
* @var mixed
*/
private $resource;
@@ -35,7 +35,7 @@ final class ImapResource implements ImapResourceInterface
public function __construct($resource, MailboxInterface $mailbox = null)
{
$this->resource = $resource;
$this->mailbox = $mailbox;
$this->mailbox = $mailbox;
}
/**
@@ -69,13 +69,13 @@ final class ImapResource implements ImapResourceInterface
*/
private function initMailbox(): void
{
if (null === $this->mailbox || $this->isMailboxOpen()) {
if (null === $this->mailbox || self::isMailboxOpen($this->mailbox, $this->resource)) {
return;
}
\imap_reopen($this->resource, $this->mailbox->getFullEncodedName());
if ($this->isMailboxOpen()) {
if (self::isMailboxOpen($this->mailbox, $this->resource)) {
return;
}
@@ -85,18 +85,18 @@ final class ImapResource implements ImapResourceInterface
/**
* Check whether the current mailbox is open.
*
* @return bool
* @param mixed $resource
*/
private function isMailboxOpen(): bool
private static function isMailboxOpen(MailboxInterface $mailbox, $resource): bool
{
$currentMailboxName = $this->mailbox->getFullEncodedName();
$currentMailboxName = $mailbox->getFullEncodedName();
if ($currentMailboxName === self::$lastMailboxUsedCache) {
return true;
}
self::$lastMailboxUsedCache = null;
$check = \imap_check($this->resource);
$return = false !== $check && $check->Mailbox === $currentMailboxName;
$check = \imap_check($resource);
$return = false !== $check && $check->Mailbox === $currentMailboxName;
if (true === $return) {
self::$lastMailboxUsedCache = $currentMailboxName;

View File

@@ -5,6 +5,8 @@ declare(strict_types=1);
namespace Ddeboer\Imap;
use DateTimeInterface;
use Ddeboer\Imap\Exception\ImapNumMsgException;
use Ddeboer\Imap\Exception\ImapStatusException;
use Ddeboer\Imap\Exception\InvalidSearchCriteriaException;
use Ddeboer\Imap\Exception\MessageCopyException;
use Ddeboer\Imap\Exception\MessageMoveException;
@@ -41,8 +43,8 @@ final class Mailbox implements MailboxInterface
public function __construct(ImapResourceInterface $resource, string $name, \stdClass $info)
{
$this->resource = new ImapResource($resource->getStream(), $this);
$this->name = $name;
$this->info = $info;
$this->name = $name;
$this->info = $info;
}
/**
@@ -62,7 +64,10 @@ final class Mailbox implements MailboxInterface
*/
public function getEncodedName(): string
{
return \preg_replace('/^{.+}/', '', $this->info->name);
/** @var string $name */
$name = $this->info->name;
return (string) \preg_replace('/^{.+}/', '', $name);
}
/**
@@ -102,7 +107,13 @@ final class Mailbox implements MailboxInterface
*/
public function count()
{
return \imap_num_msg($this->resource->getStream());
$return = \imap_num_msg($this->resource->getStream());
if (false === $return) {
throw new ImapNumMsgException('imap_num_msg failed');
}
return $return;
}
/**
@@ -114,7 +125,13 @@ final class Mailbox implements MailboxInterface
*/
public function getStatus(int $flags = null): \stdClass
{
return \imap_status($this->resource->getStream(), $this->getFullEncodedName(), $flags ?? \SA_ALL);
$return = \imap_status($this->resource->getStream(), $this->getFullEncodedName(), $flags ?? \SA_ALL);
if (false === $return) {
throw new ImapStatusException('imap_status failed');
}
return $return;
}
/**
@@ -150,7 +167,7 @@ final class Mailbox implements MailboxInterface
*
* @return MessageIteratorInterface
*/
public function getMessages(ConditionInterface $search = null, int $sortCriteria = null, bool $descending = false): MessageIteratorInterface
public function getMessages(ConditionInterface $search = null, int $sortCriteria = null, bool $descending = false, string $charset = null): MessageIteratorInterface
{
if (null === $search) {
$search = new All();
@@ -162,9 +179,27 @@ final class Mailbox implements MailboxInterface
\imap_errors();
if (null !== $sortCriteria) {
$messageNumbers = \imap_sort($this->resource->getStream(), $sortCriteria, $descending ? 1 : 0, \SE_UID, $query);
$params = [
$this->resource->getStream(),
$sortCriteria,
$descending ? 1 : 0,
\SE_UID,
$query,
];
if (null !== $charset) {
$params[] = $charset;
}
$messageNumbers = \imap_sort(...$params);
} else {
$messageNumbers = \imap_search($this->resource->getStream(), $query, \SE_UID);
$params = [
$this->resource->getStream(),
$query,
\SE_UID,
];
if (null !== $charset) {
$params[] = $charset;
}
$messageNumbers = \imap_search(...$params);
}
if (false === $messageNumbers) {
if (false !== \imap_last_error()) {
@@ -189,15 +224,15 @@ final class Mailbox implements MailboxInterface
{
\imap_errors();
$overview = \imap_fetch_overview($this->resource->getStream(), $sequence, FT_UID);
if (empty($overview)) {
$overview = \imap_fetch_overview($this->resource->getStream(), $sequence, \FT_UID);
if (\is_array($overview) && [] !== $overview) {
$messageNumbers = \array_column($overview, 'uid');
} else {
if (false !== \imap_last_error()) {
throw new InvalidSearchCriteriaException(\sprintf('Invalid sequence [%s]', $sequence));
}
$messageNumbers = [];
} else {
$messageNumbers = \array_column($overview, 'uid');
}
return new MessageIterator($this->resource, $messageNumbers);
@@ -258,8 +293,9 @@ final class Mailbox implements MailboxInterface
*/
public function getThread(): array
{
\set_error_handler(function () {});
\set_error_handler(static function () {});
/** @var array|false $tree */
$tree = \imap_thread($this->resource->getStream());
\restore_error_handler();
@@ -314,6 +350,6 @@ final class Mailbox implements MailboxInterface
$messageIds = \implode(',', $messageIds);
}
return (string) $messageIds;
return $messageIds;
}
}

View File

@@ -83,7 +83,7 @@ interface MailboxInterface extends \Countable, \IteratorAggregate
*
* @return MessageIteratorInterface
*/
public function getMessages(ConditionInterface $search = null, int $sortCriteria = null, bool $descending = false): MessageIteratorInterface;
public function getMessages(ConditionInterface $search = null, int $sortCriteria = null, bool $descending = false, string $charset = null): MessageIteratorInterface;
/**
* Get message iterator for a sequence.

View File

@@ -4,12 +4,14 @@ declare(strict_types=1);
namespace Ddeboer\Imap;
use Ddeboer\Imap\Exception\ImapFetchheaderException;
use Ddeboer\Imap\Exception\InvalidHeadersException;
use Ddeboer\Imap\Exception\MessageCopyException;
use Ddeboer\Imap\Exception\MessageDeleteException;
use Ddeboer\Imap\Exception\MessageDoesNotExistException;
use Ddeboer\Imap\Exception\MessageMoveException;
use Ddeboer\Imap\Exception\MessageStructureException;
use Ddeboer\Imap\Exception\MessageUndeleteException;
/**
* An IMAP message (e-mail).
@@ -21,6 +23,11 @@ final class Message extends Message\AbstractMessage implements MessageInterface
*/
private $messageNumberVerified = false;
/**
* @var int
*/
private $imapMsgNo = 0;
/**
* @var bool
*/
@@ -65,8 +72,8 @@ final class Message extends Message\AbstractMessage implements MessageInterface
$messageNumber = $this->getNumber();
$errorMessage = null;
$errorNumber = 0;
\set_error_handler(function ($nr, $message) use (&$errorMessage, &$errorNumber) {
$errorNumber = 0;
\set_error_handler(static function ($nr, $message) use (&$errorMessage, &$errorNumber) {
$errorMessage = $message;
$errorNumber = $nr;
});
@@ -104,6 +111,8 @@ final class Message extends Message\AbstractMessage implements MessageInterface
$msgno = \imap_msgno($this->resource->getStream(), $messageNumber);
if (\is_numeric($msgno) && $msgno > 0) {
$this->imapMsgNo = $msgno;
return;
}
@@ -113,6 +122,14 @@ final class Message extends Message\AbstractMessage implements MessageInterface
));
}
private function getMsgNo(): int
{
// Triggers assertMessageExists()
$this->getNumber();
return $this->imapMsgNo;
}
/**
* Get raw message headers.
*
@@ -121,7 +138,13 @@ final class Message extends Message\AbstractMessage implements MessageInterface
public function getRawHeaders(): string
{
if (null === $this->rawHeaders) {
$this->rawHeaders = \imap_fetchheader($this->resource->getStream(), $this->getNumber(), \FT_UID);
$rawHeaders = \imap_fetchheader($this->resource->getStream(), $this->getNumber(), \FT_UID);
if (false === $rawHeaders) {
throw new ImapFetchheaderException('imap_fetchheader failed');
}
$this->rawHeaders = $rawHeaders;
}
return $this->rawHeaders;
@@ -152,7 +175,7 @@ final class Message extends Message\AbstractMessage implements MessageInterface
// imap_headerinfo is much faster than imap_fetchheader
// imap_headerinfo returns only a subset of all mail headers,
// but it does include the message flags.
$headers = \imap_headerinfo($this->resource->getStream(), \imap_msgno($this->resource->getStream(), $this->getNumber()));
$headers = \imap_headerinfo($this->resource->getStream(), $this->getMsgNo());
if (false === $headers) {
// @see https://github.com/ddeboer/imap/issues/358
throw new InvalidHeadersException(\sprintf('Message "%s" has invalid headers', $this->getNumber()));
@@ -314,6 +337,20 @@ final class Message extends Message\AbstractMessage implements MessageInterface
}
}
/**
* Undelete message.
*
* @throws MessageUndeleteException
*/
public function undelete(): void
{
// 'deleted' header changed, force to reload headers, would be better to set deleted flag to false on header
$this->clearHeaders();
if (!\imap_undelete($this->resource->getStream(), $this->getNumber(), \FT_UID)) {
throw new MessageUndeleteException(\sprintf('Message "%s" cannot be undeleted', $this->getNumber()));
}
}
/**
* Set Flag Message.
*

View File

@@ -111,6 +111,7 @@ abstract class AbstractMessage extends AbstractPart
*/
final public function getDate(): ?\DateTimeImmutable
{
/** @var null|string $dateHeader */
$dateHeader = $this->getHeaders()->get('date');
if (null === $dateHeader) {
return null;
@@ -118,9 +119,9 @@ abstract class AbstractMessage extends AbstractPart
$alteredValue = $dateHeader;
$alteredValue = \str_replace(',', '', $alteredValue);
$alteredValue = \preg_replace('/^[a-zA-Z]+ ?/', '', $alteredValue);
$alteredValue = \preg_replace('/ +\(.*\)/', '', $alteredValue);
$alteredValue = \preg_replace('/\bUT\b/', 'UTC', $alteredValue);
$alteredValue = (string) \preg_replace('/^[a-zA-Z]+ ?/', '', $alteredValue);
$alteredValue = (string) \preg_replace('/ +\(.*\)/', '', $alteredValue);
$alteredValue = (string) \preg_replace('/\bUT\b/', 'UTC', $alteredValue);
if (0 === \preg_match('/\d\d:\d\d:\d\d.* [\+\-]\d\d:?\d\d/', $alteredValue)) {
$alteredValue .= ' +0000';
}
@@ -230,29 +231,32 @@ abstract class AbstractMessage extends AbstractPart
final public function getAttachments(): array
{
if (null === $this->attachments) {
static $gatherAttachments;
if (null === $gatherAttachments) {
$gatherAttachments = static function (PartInterface $part) use (&$gatherAttachments): array {
$attachments = [];
foreach ($part->getParts() as $childPart) {
if ($childPart instanceof Attachment) {
$attachments[] = $childPart;
}
if ($childPart->hasChildren()) {
$attachments = \array_merge($attachments, $gatherAttachments($childPart));
}
}
return $attachments;
};
}
$this->attachments = $gatherAttachments($this);
$this->attachments = self::gatherAttachments($this);
}
return $this->attachments;
}
/**
* @param PartInterface $part
*
* @return array
*/
private static function gatherAttachments(PartInterface $part): array
{
$attachments = [];
foreach ($part->getParts() as $childPart) {
if ($childPart instanceof Attachment) {
$attachments[] = $childPart;
}
if ($childPart->hasChildren()) {
$attachments = \array_merge($attachments, self::gatherAttachments($childPart));
}
}
return $attachments;
}
/**
* Does this message have attachments?
*
@@ -264,7 +268,7 @@ abstract class AbstractMessage extends AbstractPart
}
/**
* @param array $addresses Addesses
* @param \stdClass[] $addresses
*
* @return array
*/

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Ddeboer\Imap\Message;
use Ddeboer\Imap\Exception\ImapFetchbodyException;
use Ddeboer\Imap\Exception\UnexpectedEncodingException;
use Ddeboer\Imap\ImapResourceInterface;
use Ddeboer\Imap\Message;
@@ -68,6 +69,11 @@ abstract class AbstractPart implements PartInterface
*/
private $disposition;
/**
* @var null|string
*/
private $description;
/**
* @var null|string
*/
@@ -97,25 +103,25 @@ abstract class AbstractPart implements PartInterface
* @var array
*/
private static $typesMap = [
\TYPETEXT => self::TYPE_TEXT,
\TYPEMULTIPART => self::TYPE_MULTIPART,
\TYPEMESSAGE => self::TYPE_MESSAGE,
\TYPETEXT => self::TYPE_TEXT,
\TYPEMULTIPART => self::TYPE_MULTIPART,
\TYPEMESSAGE => self::TYPE_MESSAGE,
\TYPEAPPLICATION => self::TYPE_APPLICATION,
\TYPEAUDIO => self::TYPE_AUDIO,
\TYPEIMAGE => self::TYPE_IMAGE,
\TYPEVIDEO => self::TYPE_VIDEO,
\TYPEMODEL => self::TYPE_MODEL,
\TYPEOTHER => self::TYPE_OTHER,
\TYPEAUDIO => self::TYPE_AUDIO,
\TYPEIMAGE => self::TYPE_IMAGE,
\TYPEVIDEO => self::TYPE_VIDEO,
\TYPEMODEL => self::TYPE_MODEL,
\TYPEOTHER => self::TYPE_OTHER,
];
/**
* @var array
*/
private static $encodingsMap = [
\ENC7BIT => self::ENCODING_7BIT,
\ENC8BIT => self::ENCODING_8BIT,
\ENCBINARY => self::ENCODING_BINARY,
\ENCBASE64 => self::ENCODING_BASE64,
\ENC7BIT => self::ENCODING_7BIT,
\ENC8BIT => self::ENCODING_8BIT,
\ENCBINARY => self::ENCODING_BINARY,
\ENCBASE64 => self::ENCODING_BASE64,
\ENCQUOTEDPRINTABLE => self::ENCODING_QUOTED_PRINTABLE,
];
@@ -123,9 +129,9 @@ abstract class AbstractPart implements PartInterface
* @var array
*/
private static $attachmentKeys = [
'name' => true,
'filename' => true,
'name*' => true,
'name' => true,
'filename' => true,
'name*' => true,
'filename*' => true,
];
@@ -143,9 +149,9 @@ abstract class AbstractPart implements PartInterface
string $partNumber,
\stdClass $structure
) {
$this->resource = $resource;
$this->resource = $resource;
$this->messageNumber = $messageNumber;
$this->partNumber = $partNumber;
$this->partNumber = $partNumber;
$this->setStructure($structure);
}
@@ -269,6 +275,18 @@ abstract class AbstractPart implements PartInterface
return $this->disposition;
}
/**
* Part description.
*
* @return null|string
*/
final public function getDescription(): ?string
{
$this->lazyParseStructure();
return $this->description;
}
/**
* Part bytes.
*
@@ -341,7 +359,7 @@ abstract class AbstractPart implements PartInterface
$content = $this->getContent();
if (self::ENCODING_BASE64 === $this->getEncoding()) {
$content = \base64_decode($content);
$content = \base64_decode($content, false);
} elseif (self::ENCODING_QUOTED_PRINTABLE === $this->getEncoding()) {
$content = \quoted_printable_decode($content);
}
@@ -371,12 +389,18 @@ abstract class AbstractPart implements PartInterface
*/
final protected function doGetContent(string $partNumber): string
{
return \imap_fetchbody(
$return = \imap_fetchbody(
$this->resource->getStream(),
$this->getNumber(),
$partNumber,
\FT_UID | \FT_PEEK
);
if (false === $return) {
throw new ImapFetchbodyException('imap_fetchbody failed');
}
return $return;
}
/**
@@ -406,7 +430,7 @@ abstract class AbstractPart implements PartInterface
/**
* Get current child part.
*
* @return mixed
* @return \RecursiveIterator
*/
final public function getChildren()
{
@@ -483,12 +507,16 @@ abstract class AbstractPart implements PartInterface
// In our context, \ENCOTHER is as useful as an uknown encoding
$this->encoding = self::$encodingsMap[$this->structure->encoding] ?? self::ENCODING_UNKNOWN;
$this->subtype = $this->structure->subtype;
$this->subtype = $this->structure->subtype;
foreach (['disposition', 'bytes', 'description'] as $optional) {
if (isset($this->structure->{$optional})) {
$this->{$optional} = $this->structure->{$optional};
}
if (isset($this->structure->bytes)) {
$this->bytes = $this->structure->bytes;
}
if ($this->structure->ifdisposition) {
$this->disposition = $this->structure->disposition;
}
if ($this->structure->ifdescription) {
$this->description = $this->structure->description;
}
$this->parameters = new Parameters();
@@ -573,6 +601,10 @@ abstract class AbstractPart implements PartInterface
}
*/
if (self::SUBTYPE_RFC822 === \strtoupper($part->subtype)) {
return true;
}
return false;
}
}

View File

@@ -25,11 +25,16 @@ final class Attachment extends AbstractPart implements AttachmentInterface
/**
* Get attachment file size.
*
* @return int Number of bytes
* @return null|int Number of bytes
*/
public function getSize()
{
return $this->getParameters()->get('size');
$size = $this->getParameters()->get('size');
if (\is_numeric($size)) {
$size = (int) $size;
}
return $size;
}
/**

View File

@@ -19,7 +19,7 @@ interface AttachmentInterface extends PartInterface
/**
* Get attachment file size.
*
* @return int Number of bytes
* @return null|int Number of bytes
*/
public function getSize();

View File

@@ -36,9 +36,9 @@ final class EmailAddress
*/
public function __construct(string $mailbox, string $hostname = null, string $name = null)
{
$this->mailbox = $mailbox;
$this->mailbox = $mailbox;
$this->hostname = $hostname;
$this->name = $name;
$this->name = $name;
if (null !== $hostname) {
$this->address = $mailbox . '@' . $hostname;

View File

@@ -43,7 +43,7 @@ final class EmbeddedMessage extends AbstractMessage implements EmbeddedMessageIn
public function getRawHeaders(): string
{
if (null === $this->rawHeaders) {
$rawHeaders = \explode("\r\n\r\n", $this->getRawMessage(), 2);
$rawHeaders = \explode("\r\n\r\n", $this->getRawMessage(), 2);
$this->rawHeaders = \current($rawHeaders);
}

View File

@@ -31,7 +31,7 @@ final class Headers extends Parameters
*
* @param string $key
*
* @return null|string
* @return mixed
*/
public function get(string $key)
{
@@ -58,9 +58,10 @@ final class Headers extends Parameters
case 'reply_to':
case 'sender':
case 'return_path':
/** @var \stdClass $address */
foreach ($value as $address) {
if (isset($address->mailbox)) {
$address->host = $address->host ?? null;
$address->host = $address->host ?? null;
$address->personal = isset($address->personal) ? $this->decode($address->personal) : null;
}
}

View File

@@ -10,7 +10,7 @@ class Parameters extends \ArrayIterator
* @var array
*/
private static $attachmentCustomKeys = [
'name*' => 'name',
'name*' => 'name',
'filename*' => 'filename',
];
@@ -34,7 +34,7 @@ class Parameters extends \ArrayIterator
if (isset(self::$attachmentCustomKeys[$key])) {
$key = self::$attachmentCustomKeys[$key];
}
$value = $this->decode($parameter->value);
$value = $this->decode($parameter->value);
$this[$key] = $value;
}
}
@@ -71,8 +71,8 @@ class Parameters extends \ArrayIterator
}
// RFC2231
if (1 === \preg_match('/^(?<encoding>[^\']+)\'[^\']*?\'(?<urltext>.+)$/', $text, $matches)) {
$hasInvalidChars = \preg_match('#[^%a-zA-Z0-9\-_\.\+]#', $matches['urltext']);
$hasEscapedChars = \preg_match('#%[a-zA-Z0-9]{2}#', $matches['urltext']);
$hasInvalidChars = 1 === \preg_match('#[^%a-zA-Z0-9\-_\.\+]#', $matches['urltext']);
$hasEscapedChars = 1 === \preg_match('#%[a-zA-Z0-9]{2}#', $matches['urltext']);
if (!$hasInvalidChars && $hasEscapedChars) {
$text = Transcoder::decode(\urldecode($matches['urltext']), $matches['encoding']);
}

View File

@@ -9,26 +9,27 @@ namespace Ddeboer\Imap\Message;
*/
interface PartInterface extends \RecursiveIterator
{
const TYPE_TEXT = 'text';
const TYPE_MULTIPART = 'multipart';
const TYPE_MESSAGE = 'message';
const TYPE_APPLICATION = 'application';
const TYPE_AUDIO = 'audio';
const TYPE_IMAGE = 'image';
const TYPE_VIDEO = 'video';
const TYPE_MODEL = 'model';
const TYPE_OTHER = 'other';
const TYPE_UNKNOWN = 'unknown';
public const TYPE_TEXT = 'text';
public const TYPE_MULTIPART = 'multipart';
public const TYPE_MESSAGE = 'message';
public const TYPE_APPLICATION = 'application';
public const TYPE_AUDIO = 'audio';
public const TYPE_IMAGE = 'image';
public const TYPE_VIDEO = 'video';
public const TYPE_MODEL = 'model';
public const TYPE_OTHER = 'other';
public const TYPE_UNKNOWN = 'unknown';
const ENCODING_7BIT = '7bit';
const ENCODING_8BIT = '8bit';
const ENCODING_BINARY = 'binary';
const ENCODING_BASE64 = 'base64';
const ENCODING_QUOTED_PRINTABLE = 'quoted-printable';
const ENCODING_UNKNOWN = 'unknown';
public const ENCODING_7BIT = '7bit';
public const ENCODING_8BIT = '8bit';
public const ENCODING_BINARY = 'binary';
public const ENCODING_BASE64 = 'base64';
public const ENCODING_QUOTED_PRINTABLE = 'quoted-printable';
public const ENCODING_UNKNOWN = 'unknown';
const SUBTYPE_PLAIN = 'PLAIN';
const SUBTYPE_HTML = 'HTML';
public const SUBTYPE_PLAIN = 'PLAIN';
public const SUBTYPE_HTML = 'HTML';
public const SUBTYPE_RFC822 = 'RFC822';
/**
* Get message number (from headers).
@@ -72,6 +73,13 @@ interface PartInterface extends \RecursiveIterator
*/
public function getDisposition(): ?string;
/**
* Part description.
*
* @return null|string
*/
public function getDescription(): ?string;
/**
* Part bytes.
*

View File

@@ -17,247 +17,247 @@ final class Transcoder
* @see https://msdn.microsoft.com/en-us/library/cc194829.aspx
*/
private static $charsetAliases = [
'128' => 'Shift_JIS',
'129' => 'EUC-KR',
'134' => 'GB2312',
'136' => 'Big5',
'161' => 'windows-1253',
'162' => 'windows-1254',
'177' => 'windows-1255',
'178' => 'windows-1256',
'186' => 'windows-1257',
'204' => 'windows-1251',
'222' => 'windows-874',
'238' => 'windows-1250',
'5601' => 'EUC-KR',
'646' => 'us-ascii',
'850' => 'IBM850',
'852' => 'IBM852',
'855' => 'IBM855',
'857' => 'IBM857',
'862' => 'IBM862',
'864' => 'IBM864',
'864i' => 'IBM864i',
'866' => 'IBM866',
'ansi-1251' => 'windows-1251',
'ansi_x3.4-1968' => 'us-ascii',
'arabic' => 'ISO-8859-6',
'ascii' => 'us-ascii',
'asmo-708' => 'ISO-8859-6',
'big5-hkscs' => 'Big5',
'chinese' => 'GB2312',
'cn-big5' => 'Big5',
'cns11643' => 'x-euc-tw',
'cp-866' => 'IBM866',
'cp1250' => 'windows-1250',
'cp1251' => 'windows-1251',
'cp1252' => 'windows-1252',
'cp1253' => 'windows-1253',
'cp1254' => 'windows-1254',
'cp1255' => 'windows-1255',
'cp1256' => 'windows-1256',
'cp1257' => 'windows-1257',
'cp1258' => 'windows-1258',
'cp819' => 'ISO-8859-1',
'cp850' => 'IBM850',
'cp852' => 'IBM852',
'cp855' => 'IBM855',
'cp857' => 'IBM857',
'cp862' => 'IBM862',
'cp864' => 'IBM864',
'cp864i' => 'IBM864i',
'cp866' => 'IBM866',
'cp932' => 'Shift_JIS',
'csbig5' => 'Big5',
'cseucjpkdfmtjapanese' => 'EUC-JP',
'cseuckr' => 'EUC-KR',
'cseucpkdfmtjapanese' => 'EUC-JP',
'csgb2312' => 'GB2312',
'csibm850' => 'IBM850',
'csibm852' => 'IBM852',
'csibm855' => 'IBM855',
'csibm857' => 'IBM857',
'csibm862' => 'IBM862',
'csibm864' => 'IBM864',
'csibm864i' => 'IBM864i',
'csibm866' => 'IBM866',
'csiso103t618bit' => 'T.61-8bit',
'csiso111ecmacyrillic' => 'ISO-IR-111',
'csiso2022jp' => 'ISO-2022-JP',
'csiso2022jp2' => 'ISO-2022-JP',
'csiso2022kr' => 'ISO-2022-KR',
'csiso58gb231280' => 'GB2312',
'csiso88596e' => 'ISO-8859-6-E',
'csiso88596i' => 'ISO-8859-6-I',
'csiso88598e' => 'ISO-8859-8-E',
'csiso88598i' => 'ISO-8859-8-I',
'csisolatin1' => 'ISO-8859-1',
'csisolatin2' => 'ISO-8859-2',
'csisolatin3' => 'ISO-8859-3',
'csisolatin4' => 'ISO-8859-4',
'csisolatin5' => 'ISO-8859-9',
'csisolatin6' => 'ISO-8859-10',
'csisolatin9' => 'ISO-8859-15',
'csisolatinarabic' => 'ISO-8859-6',
'csisolatincyrillic' => 'ISO-8859-5',
'csisolatingreek' => 'ISO-8859-7',
'csisolatinhebrew' => 'ISO-8859-8',
'cskoi8r' => 'KOI8-R',
'csksc56011987' => 'EUC-KR',
'csmacintosh' => 'x-mac-roman',
'csshiftjis' => 'Shift_JIS',
'csueckr' => 'EUC-KR',
'csunicode' => 'UTF-16BE',
'csunicode11' => 'UTF-16BE',
'csunicode11utf7' => 'UTF-7',
'csunicodeascii' => 'UTF-16BE',
'csunicodelatin1' => 'UTF-16BE',
'csviqr' => 'VIQR',
'csviscii' => 'VISCII',
'cyrillic' => 'ISO-8859-5',
'dos-874' => 'windows-874',
'ecma-114' => 'ISO-8859-6',
'ecma-118' => 'ISO-8859-7',
'ecma-cyrillic' => 'ISO-IR-111',
'elot_928' => 'ISO-8859-7',
'gb_2312' => 'GB2312',
'gb_2312-80' => 'GB2312',
'gbk' => 'x-gbk',
'greek' => 'ISO-8859-7',
'greek8' => 'ISO-8859-7',
'hebrew' => 'ISO-8859-8',
'ibm-864' => 'IBM864',
'ibm-864i' => 'IBM864i',
'ibm819' => 'ISO-8859-1',
'ibm874' => 'windows-874',
'iso-10646' => 'UTF-16BE',
'iso-10646-j-1' => 'UTF-16BE',
'iso-10646-ucs-2' => 'UTF-16BE',
'iso-10646-ucs-4' => 'UTF-32BE',
'iso-10646-ucs-basic' => 'UTF-16BE',
'iso-10646-unicode-latin1' => 'UTF-16BE',
'iso-2022-cn-ext' => 'ISO-2022-CN',
'iso-2022-jp-2' => 'ISO-2022-JP',
'iso-8859-8i' => 'ISO-8859-8-I',
'iso-ir-100' => 'ISO-8859-1',
'iso-ir-101' => 'ISO-8859-2',
'iso-ir-103' => 'T.61-8bit',
'iso-ir-109' => 'ISO-8859-3',
'iso-ir-110' => 'ISO-8859-4',
'iso-ir-126' => 'ISO-8859-7',
'iso-ir-127' => 'ISO-8859-6',
'iso-ir-138' => 'ISO-8859-8',
'iso-ir-144' => 'ISO-8859-5',
'iso-ir-148' => 'ISO-8859-9',
'iso-ir-149' => 'EUC-KR',
'iso-ir-157' => 'ISO-8859-10',
'iso-ir-58' => 'GB2312',
'iso8859-1' => 'ISO-8859-1',
'iso8859-10' => 'ISO-8859-10',
'iso8859-11' => 'ISO-8859-11',
'iso8859-13' => 'ISO-8859-13',
'iso8859-14' => 'ISO-8859-14',
'iso8859-15' => 'ISO-8859-15',
'iso8859-2' => 'ISO-8859-2',
'iso8859-3' => 'ISO-8859-3',
'iso8859-4' => 'ISO-8859-4',
'iso8859-5' => 'ISO-8859-5',
'iso8859-6' => 'ISO-8859-6',
'iso8859-7' => 'ISO-8859-7',
'iso8859-8' => 'ISO-8859-8',
'iso8859-9' => 'ISO-8859-9',
'iso88591' => 'ISO-8859-1',
'iso885910' => 'ISO-8859-10',
'iso885911' => 'ISO-8859-11',
'iso885912' => 'ISO-8859-12',
'iso885913' => 'ISO-8859-13',
'iso885914' => 'ISO-8859-14',
'iso885915' => 'ISO-8859-15',
'iso88592' => 'ISO-8859-2',
'iso88593' => 'ISO-8859-3',
'iso88594' => 'ISO-8859-4',
'iso88595' => 'ISO-8859-5',
'iso88596' => 'ISO-8859-6',
'iso88597' => 'ISO-8859-7',
'iso88598' => 'ISO-8859-8',
'iso88599' => 'ISO-8859-9',
'iso_8859-1' => 'ISO-8859-1',
'iso_8859-15' => 'ISO-8859-15',
'iso_8859-1:1987' => 'ISO-8859-1',
'iso_8859-2' => 'ISO-8859-2',
'iso_8859-2:1987' => 'ISO-8859-2',
'iso_8859-3' => 'ISO-8859-3',
'iso_8859-3:1988' => 'ISO-8859-3',
'iso_8859-4' => 'ISO-8859-4',
'iso_8859-4:1988' => 'ISO-8859-4',
'iso_8859-5' => 'ISO-8859-5',
'iso_8859-5:1988' => 'ISO-8859-5',
'iso_8859-6' => 'ISO-8859-6',
'iso_8859-6:1987' => 'ISO-8859-6',
'iso_8859-7' => 'ISO-8859-7',
'iso_8859-7:1987' => 'ISO-8859-7',
'iso_8859-8' => 'ISO-8859-8',
'iso_8859-8:1988' => 'ISO-8859-8',
'iso_8859-9' => 'ISO-8859-9',
'iso_8859-9:1989' => 'ISO-8859-9',
'koi' => 'KOI8-R',
'koi8' => 'KOI8-R',
'koi8-ru' => 'KOI8-U',
'koi8_r' => 'KOI8-R',
'korean' => 'EUC-KR',
'ks_c_5601-1987' => 'EUC-KR',
'ks_c_5601-1989' => 'EUC-KR',
'ksc5601' => 'EUC-KR',
'ksc_5601' => 'EUC-KR',
'l1' => 'ISO-8859-1',
'l2' => 'ISO-8859-2',
'l3' => 'ISO-8859-3',
'l4' => 'ISO-8859-4',
'l5' => 'ISO-8859-9',
'l6' => 'ISO-8859-10',
'l9' => 'ISO-8859-15',
'latin1' => 'ISO-8859-1',
'latin2' => 'ISO-8859-2',
'latin3' => 'ISO-8859-3',
'latin4' => 'ISO-8859-4',
'latin5' => 'ISO-8859-9',
'latin6' => 'ISO-8859-10',
'logical' => 'ISO-8859-8-I',
'mac' => 'x-mac-roman',
'macintosh' => 'x-mac-roman',
'ms932' => 'Shift_JIS',
'ms_kanji' => 'Shift_JIS',
'shift-jis' => 'Shift_JIS',
'sjis' => 'Shift_JIS',
'sun_eu_greek' => 'ISO-8859-7',
't.61' => 'T.61-8bit',
'tis620' => 'TIS-620',
'unicode-1-1-utf-7' => 'UTF-7',
'unicode-1-1-utf-8' => 'UTF-8',
'unicode-2-0-utf-7' => 'UTF-7',
'visual' => 'ISO-8859-8',
'windows-31j' => 'Shift_JIS',
'windows-949' => 'EUC-KR',
'x-cp1250' => 'windows-1250',
'x-cp1251' => 'windows-1251',
'x-cp1252' => 'windows-1252',
'x-cp1253' => 'windows-1253',
'x-cp1254' => 'windows-1254',
'x-cp1255' => 'windows-1255',
'x-cp1256' => 'windows-1256',
'x-cp1257' => 'windows-1257',
'x-cp1258' => 'windows-1258',
'x-euc-jp' => 'EUC-JP',
'x-iso-10646-ucs-2-be' => 'UTF-16BE',
'x-iso-10646-ucs-2-le' => 'UTF-16LE',
'x-iso-10646-ucs-4-be' => 'UTF-32BE',
'x-iso-10646-ucs-4-le' => 'UTF-32LE',
'x-sjis' => 'Shift_JIS',
'x-unicode-2-0-utf-7' => 'UTF-7',
'x-x-big5' => 'Big5',
'zh_cn.euc' => 'GB2312',
'zh_tw-big5' => 'Big5',
'zh_tw-euc' => 'x-euc-tw',
'128' => 'Shift_JIS',
'129' => 'EUC-KR',
'134' => 'GB2312',
'136' => 'Big5',
'161' => 'windows-1253',
'162' => 'windows-1254',
'177' => 'windows-1255',
'178' => 'windows-1256',
'186' => 'windows-1257',
'204' => 'windows-1251',
'222' => 'windows-874',
'238' => 'windows-1250',
'5601' => 'EUC-KR',
'646' => 'us-ascii',
'850' => 'IBM850',
'852' => 'IBM852',
'855' => 'IBM855',
'857' => 'IBM857',
'862' => 'IBM862',
'864' => 'IBM864',
'864i' => 'IBM864i',
'866' => 'IBM866',
'ansi-1251' => 'windows-1251',
'ansi_x3.4-1968' => 'us-ascii',
'arabic' => 'ISO-8859-6',
'ascii' => 'us-ascii',
'asmo-708' => 'ISO-8859-6',
'big5-hkscs' => 'Big5',
'chinese' => 'GB2312',
'cn-big5' => 'Big5',
'cns11643' => 'x-euc-tw',
'cp-866' => 'IBM866',
'cp1250' => 'windows-1250',
'cp1251' => 'windows-1251',
'cp1252' => 'windows-1252',
'cp1253' => 'windows-1253',
'cp1254' => 'windows-1254',
'cp1255' => 'windows-1255',
'cp1256' => 'windows-1256',
'cp1257' => 'windows-1257',
'cp1258' => 'windows-1258',
'cp819' => 'ISO-8859-1',
'cp850' => 'IBM850',
'cp852' => 'IBM852',
'cp855' => 'IBM855',
'cp857' => 'IBM857',
'cp862' => 'IBM862',
'cp864' => 'IBM864',
'cp864i' => 'IBM864i',
'cp866' => 'IBM866',
'cp932' => 'Shift_JIS',
'csbig5' => 'Big5',
'cseucjpkdfmtjapanese' => 'EUC-JP',
'cseuckr' => 'EUC-KR',
'cseucpkdfmtjapanese' => 'EUC-JP',
'csgb2312' => 'GB2312',
'csibm850' => 'IBM850',
'csibm852' => 'IBM852',
'csibm855' => 'IBM855',
'csibm857' => 'IBM857',
'csibm862' => 'IBM862',
'csibm864' => 'IBM864',
'csibm864i' => 'IBM864i',
'csibm866' => 'IBM866',
'csiso103t618bit' => 'T.61-8bit',
'csiso111ecmacyrillic' => 'ISO-IR-111',
'csiso2022jp' => 'ISO-2022-JP',
'csiso2022jp2' => 'ISO-2022-JP',
'csiso2022kr' => 'ISO-2022-KR',
'csiso58gb231280' => 'GB2312',
'csiso88596e' => 'ISO-8859-6-E',
'csiso88596i' => 'ISO-8859-6-I',
'csiso88598e' => 'ISO-8859-8-E',
'csiso88598i' => 'ISO-8859-8-I',
'csisolatin1' => 'ISO-8859-1',
'csisolatin2' => 'ISO-8859-2',
'csisolatin3' => 'ISO-8859-3',
'csisolatin4' => 'ISO-8859-4',
'csisolatin5' => 'ISO-8859-9',
'csisolatin6' => 'ISO-8859-10',
'csisolatin9' => 'ISO-8859-15',
'csisolatinarabic' => 'ISO-8859-6',
'csisolatincyrillic' => 'ISO-8859-5',
'csisolatingreek' => 'ISO-8859-7',
'csisolatinhebrew' => 'ISO-8859-8',
'cskoi8r' => 'KOI8-R',
'csksc56011987' => 'EUC-KR',
'csmacintosh' => 'x-mac-roman',
'csshiftjis' => 'Shift_JIS',
'csueckr' => 'EUC-KR',
'csunicode' => 'UTF-16BE',
'csunicode11' => 'UTF-16BE',
'csunicode11utf7' => 'UTF-7',
'csunicodeascii' => 'UTF-16BE',
'csunicodelatin1' => 'UTF-16BE',
'csviqr' => 'VIQR',
'csviscii' => 'VISCII',
'cyrillic' => 'ISO-8859-5',
'dos-874' => 'windows-874',
'ecma-114' => 'ISO-8859-6',
'ecma-118' => 'ISO-8859-7',
'ecma-cyrillic' => 'ISO-IR-111',
'elot_928' => 'ISO-8859-7',
'gb_2312' => 'GB2312',
'gb_2312-80' => 'GB2312',
'greek' => 'ISO-8859-7',
'greek8' => 'ISO-8859-7',
'hebrew' => 'ISO-8859-8',
'ibm-864' => 'IBM864',
'ibm-864i' => 'IBM864i',
'ibm819' => 'ISO-8859-1',
'ibm874' => 'windows-874',
'iso-10646' => 'UTF-16BE',
'iso-10646-j-1' => 'UTF-16BE',
'iso-10646-ucs-2' => 'UTF-16BE',
'iso-10646-ucs-4' => 'UTF-32BE',
'iso-10646-ucs-basic' => 'UTF-16BE',
'iso-10646-unicode-latin1' => 'UTF-16BE',
'iso-2022-cn-ext' => 'ISO-2022-CN',
'iso-2022-jp-2' => 'ISO-2022-JP',
'iso-8859-8i' => 'ISO-8859-8-I',
'iso-ir-100' => 'ISO-8859-1',
'iso-ir-101' => 'ISO-8859-2',
'iso-ir-103' => 'T.61-8bit',
'iso-ir-109' => 'ISO-8859-3',
'iso-ir-110' => 'ISO-8859-4',
'iso-ir-126' => 'ISO-8859-7',
'iso-ir-127' => 'ISO-8859-6',
'iso-ir-138' => 'ISO-8859-8',
'iso-ir-144' => 'ISO-8859-5',
'iso-ir-148' => 'ISO-8859-9',
'iso-ir-149' => 'EUC-KR',
'iso-ir-157' => 'ISO-8859-10',
'iso-ir-58' => 'GB2312',
'iso8859-1' => 'ISO-8859-1',
'iso8859-10' => 'ISO-8859-10',
'iso8859-11' => 'ISO-8859-11',
'iso8859-13' => 'ISO-8859-13',
'iso8859-14' => 'ISO-8859-14',
'iso8859-15' => 'ISO-8859-15',
'iso8859-2' => 'ISO-8859-2',
'iso8859-3' => 'ISO-8859-3',
'iso8859-4' => 'ISO-8859-4',
'iso8859-5' => 'ISO-8859-5',
'iso8859-6' => 'ISO-8859-6',
'iso8859-7' => 'ISO-8859-7',
'iso8859-8' => 'ISO-8859-8',
'iso8859-9' => 'ISO-8859-9',
'iso88591' => 'ISO-8859-1',
'iso885910' => 'ISO-8859-10',
'iso885911' => 'ISO-8859-11',
'iso885912' => 'ISO-8859-12',
'iso885913' => 'ISO-8859-13',
'iso885914' => 'ISO-8859-14',
'iso885915' => 'ISO-8859-15',
'iso88592' => 'ISO-8859-2',
'iso88593' => 'ISO-8859-3',
'iso88594' => 'ISO-8859-4',
'iso88595' => 'ISO-8859-5',
'iso88596' => 'ISO-8859-6',
'iso88597' => 'ISO-8859-7',
'iso88598' => 'ISO-8859-8',
'iso88599' => 'ISO-8859-9',
'iso_8859-1' => 'ISO-8859-1',
'iso_8859-15' => 'ISO-8859-15',
'iso_8859-1:1987' => 'ISO-8859-1',
'iso_8859-2' => 'ISO-8859-2',
'iso_8859-2:1987' => 'ISO-8859-2',
'iso_8859-3' => 'ISO-8859-3',
'iso_8859-3:1988' => 'ISO-8859-3',
'iso_8859-4' => 'ISO-8859-4',
'iso_8859-4:1988' => 'ISO-8859-4',
'iso_8859-5' => 'ISO-8859-5',
'iso_8859-5:1988' => 'ISO-8859-5',
'iso_8859-6' => 'ISO-8859-6',
'iso_8859-6:1987' => 'ISO-8859-6',
'iso_8859-7' => 'ISO-8859-7',
'iso_8859-7:1987' => 'ISO-8859-7',
'iso_8859-8' => 'ISO-8859-8',
'iso_8859-8:1988' => 'ISO-8859-8',
'iso_8859-9' => 'ISO-8859-9',
'iso_8859-9:1989' => 'ISO-8859-9',
'koi' => 'KOI8-R',
'koi8' => 'KOI8-R',
'koi8-ru' => 'KOI8-U',
'koi8_r' => 'KOI8-R',
'korean' => 'EUC-KR',
'ks_c_5601-1987' => 'EUC-KR',
'ks_c_5601-1989' => 'EUC-KR',
'ksc5601' => 'EUC-KR',
'ksc_5601' => 'EUC-KR',
'l1' => 'ISO-8859-1',
'l2' => 'ISO-8859-2',
'l3' => 'ISO-8859-3',
'l4' => 'ISO-8859-4',
'l5' => 'ISO-8859-9',
'l6' => 'ISO-8859-10',
'l9' => 'ISO-8859-15',
'latin1' => 'ISO-8859-1',
'latin2' => 'ISO-8859-2',
'latin3' => 'ISO-8859-3',
'latin4' => 'ISO-8859-4',
'latin5' => 'ISO-8859-9',
'latin6' => 'ISO-8859-10',
'logical' => 'ISO-8859-8-I',
'mac' => 'x-mac-roman',
'macintosh' => 'x-mac-roman',
'ms932' => 'Shift_JIS',
'ms_kanji' => 'Shift_JIS',
'shift-jis' => 'Shift_JIS',
'sjis' => 'Shift_JIS',
'sun_eu_greek' => 'ISO-8859-7',
't.61' => 'T.61-8bit',
'tis620' => 'TIS-620',
'unicode-1-1-utf-7' => 'UTF-7',
'unicode-1-1-utf-8' => 'UTF-8',
'unicode-2-0-utf-7' => 'UTF-7',
'visual' => 'ISO-8859-8',
'windows-31j' => 'Shift_JIS',
'windows-949' => 'EUC-KR',
'x-cp1250' => 'windows-1250',
'x-cp1251' => 'windows-1251',
'x-cp1252' => 'windows-1252',
'x-cp1253' => 'windows-1253',
'x-cp1254' => 'windows-1254',
'x-cp1255' => 'windows-1255',
'x-cp1256' => 'windows-1256',
'x-cp1257' => 'windows-1257',
'x-cp1258' => 'windows-1258',
'x-euc-jp' => 'EUC-JP',
'x-gbk' => 'gbk',
'x-iso-10646-ucs-2-be' => 'UTF-16BE',
'x-iso-10646-ucs-2-le' => 'UTF-16LE',
'x-iso-10646-ucs-4-be' => 'UTF-32BE',
'x-iso-10646-ucs-4-le' => 'UTF-32LE',
'x-sjis' => 'Shift_JIS',
'x-unicode-2-0-utf-7' => 'UTF-7',
'x-x-big5' => 'Big5',
'zh_cn.euc' => 'GB2312',
'zh_tw-big5' => 'Big5',
'zh_tw-euc' => 'x-euc-tw',
];
/**
@@ -272,23 +272,23 @@ final class Transcoder
{
static $utf8Aliases = [
'unicode-1-1-utf-8' => true,
'utf8' => true,
'utf-8' => true,
'UTF8' => true,
'UTF-8' => true,
'utf8' => true,
'utf-8' => true,
'UTF8' => true,
'UTF-8' => true,
];
if (isset($utf8Aliases[$fromCharset])) {
return $text;
}
$originalFromCharset = $fromCharset;
$originalFromCharset = $fromCharset;
$lowercaseFromCharset = \strtolower($fromCharset);
if (isset(self::$charsetAliases[$lowercaseFromCharset])) {
$fromCharset = self::$charsetAliases[$lowercaseFromCharset];
}
\set_error_handler(function () {});
\set_error_handler(static function () {});
$iconvDecodedText = \iconv($fromCharset, 'UTF-8', $text);
if (false === $iconvDecodedText) {
@@ -302,8 +302,8 @@ final class Transcoder
}
$errorMessage = null;
$errorNumber = 0;
\set_error_handler(function ($nr, $message) use (&$errorMessage, &$errorNumber) {
$errorNumber = 0;
\set_error_handler(static function ($nr, $message) use (&$errorMessage, &$errorNumber) {
$errorMessage = $message;
$errorNumber = $nr;
});

View File

@@ -100,6 +100,11 @@ interface MessageInterface extends Message\BasicMessageInterface
*/
public function delete(): void;
/**
* Undelete message.
*/
public function undelete(): void;
/**
* Set Flag Message.
*

View File

@@ -32,7 +32,7 @@ abstract class AbstractDate implements ConditionInterface
*/
public function __construct(DateTimeInterface $date, string $dateFormat = 'j-M-Y')
{
$this->date = $date;
$this->date = $date;
$this->dateFormat = $dateFormat;
}

View File

@@ -43,7 +43,7 @@ final class OrConditions implements ConditionInterface
*/
public function toString(): string
{
$conditions = \array_map(function (ConditionInterface $condition) {
$conditions = \array_map(static function (ConditionInterface $condition) {
return $condition->toString();
}, $this->conditions);

View File

@@ -39,7 +39,7 @@ final class SearchExpression implements ConditionInterface
*/
public function toString(): string
{
$conditions = \array_map(function (ConditionInterface $condition) {
$conditions = \array_map(static function (ConditionInterface $condition) {
return $condition->toString();
}, $this->conditions);

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Ddeboer\Imap;
use Ddeboer\Imap\Exception\AuthenticationFailedException;
use Ddeboer\Imap\Exception\ResourceCheckFailureException;
/**
* An IMAP server.
@@ -64,12 +65,12 @@ final class Server implements ServerInterface
throw new \RuntimeException('IMAP extension must be enabled');
}
$this->hostname = $hostname;
$this->port = $port;
$this->flags = $flags ? '/' . \ltrim($flags, '/') : '';
$this->hostname = $hostname;
$this->port = $port;
$this->flags = '' !== $flags ? '/' . \ltrim($flags, '/') : '';
$this->parameters = $parameters;
$this->options = $options;
$this->retries = $retries;
$this->options = $options;
$this->retries = $retries;
}
/**
@@ -85,8 +86,8 @@ final class Server implements ServerInterface
public function authenticate(string $username, string $password): ConnectionInterface
{
$errorMessage = null;
$errorNumber = 0;
\set_error_handler(function ($nr, $message) use (&$errorMessage, &$errorNumber) {
$errorNumber = 0;
\set_error_handler(static function ($nr, $message) use (&$errorMessage, &$errorNumber) {
$errorMessage = $message;
$errorNumber = $nr;
});
@@ -111,8 +112,17 @@ final class Server implements ServerInterface
}
$check = \imap_check($resource);
$mailbox = $check->Mailbox;
$connection = \substr($mailbox, 0, \strpos($mailbox, '}') + 1);
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();