git subrepo clone https://github.com/mailcow/mailcow-dockerized.git mailcow/src/mailcow-dockerized
subrepo: subdir: "mailcow/src/mailcow-dockerized"
merged: "a832becb"
upstream: origin: "https://github.com/mailcow/mailcow-dockerized.git"
branch: "master"
commit: "a832becb"
git-subrepo: version: "0.4.3"
origin: "???"
commit: "???"
Change-Id: If5be2d621a211e164c9b6577adaa7884449f16b5
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message.php
new file mode 100644
index 0000000..7b50777
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message.php
@@ -0,0 +1,355 @@
+<?php
+
+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).
+ */
+final class Message extends Message\AbstractMessage implements MessageInterface
+{
+ /**
+ * @var bool
+ */
+ private $messageNumberVerified = false;
+
+ /**
+ * @var int
+ */
+ private $imapMsgNo = 0;
+
+ /**
+ * @var bool
+ */
+ private $structureLoaded = false;
+
+ /**
+ * @var null|Message\Headers
+ */
+ private $headers;
+
+ /**
+ * @var null|string
+ */
+ private $rawHeaders;
+
+ /**
+ * @var null|string
+ */
+ private $rawMessage;
+
+ /**
+ * Constructor.
+ *
+ * @param ImapResourceInterface $resource IMAP resource
+ * @param int $messageNumber Message number
+ */
+ public function __construct(ImapResourceInterface $resource, int $messageNumber)
+ {
+ parent::__construct($resource, $messageNumber, '1', new \stdClass());
+ }
+
+ /**
+ * Lazy load structure.
+ */
+ protected function lazyLoadStructure(): void
+ {
+ if (true === $this->structureLoaded) {
+ return;
+ }
+ $this->structureLoaded = true;
+
+ $messageNumber = $this->getNumber();
+
+ $errorMessage = null;
+ $errorNumber = 0;
+ \set_error_handler(static function ($nr, $message) use (&$errorMessage, &$errorNumber): bool {
+ $errorMessage = $message;
+ $errorNumber = $nr;
+
+ return true;
+ });
+
+ $structure = \imap_fetchstructure(
+ $this->resource->getStream(),
+ $messageNumber,
+ \FT_UID
+ );
+
+ \restore_error_handler();
+
+ if (!$structure instanceof \stdClass) {
+ throw new MessageStructureException(\sprintf(
+ 'Message "%s" structure is empty: %s',
+ $messageNumber,
+ $errorMessage
+ ), $errorNumber);
+ }
+
+ $this->setStructure($structure);
+ }
+
+ /**
+ * Ensure message exists.
+ */
+ protected function assertMessageExists(int $messageNumber): void
+ {
+ if (true === $this->messageNumberVerified) {
+ return;
+ }
+ $this->messageNumberVerified = true;
+
+ $msgno = \imap_msgno($this->resource->getStream(), $messageNumber);
+ if (\is_numeric($msgno) && $msgno > 0) {
+ $this->imapMsgNo = $msgno;
+
+ return;
+ }
+
+ throw new MessageDoesNotExistException(\sprintf(
+ 'Message "%s" does not exist',
+ $messageNumber
+ ));
+ }
+
+ private function getMsgNo(): int
+ {
+ // Triggers assertMessageExists()
+ $this->getNumber();
+
+ return $this->imapMsgNo;
+ }
+
+ /**
+ * Get raw message headers.
+ */
+ public function getRawHeaders(): string
+ {
+ if (null === $this->rawHeaders) {
+ $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;
+ }
+
+ /**
+ * Get the raw message, including all headers, parts, etc. unencoded and unparsed.
+ *
+ * @return string the raw message
+ */
+ public function getRawMessage(): string
+ {
+ if (null === $this->rawMessage) {
+ $this->rawMessage = $this->doGetContent('');
+ }
+
+ return $this->rawMessage;
+ }
+
+ /**
+ * Get message headers.
+ */
+ public function getHeaders(): Message\Headers
+ {
+ if (null === $this->headers) {
+ // 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(), $this->getMsgNo());
+ if (false === $headers) {
+ // @see https://github.com/ddeboer/imap/issues/358
+ throw new InvalidHeadersException(\sprintf('Message "%s" has invalid headers', $this->getNumber()));
+ }
+ $this->headers = new Message\Headers($headers);
+ }
+
+ return $this->headers;
+ }
+
+ /**
+ * Clearmessage headers.
+ */
+ private function clearHeaders(): void
+ {
+ $this->headers = null;
+ }
+
+ /**
+ * Get message recent flag value (from headers).
+ */
+ public function isRecent(): ?string
+ {
+ return $this->getHeaders()->get('recent');
+ }
+
+ /**
+ * Get message unseen flag value (from headers).
+ */
+ public function isUnseen(): bool
+ {
+ return 'U' === $this->getHeaders()->get('unseen');
+ }
+
+ /**
+ * Get message flagged flag value (from headers).
+ */
+ public function isFlagged(): bool
+ {
+ return 'F' === $this->getHeaders()->get('flagged');
+ }
+
+ /**
+ * Get message answered flag value (from headers).
+ */
+ public function isAnswered(): bool
+ {
+ return 'A' === $this->getHeaders()->get('answered');
+ }
+
+ /**
+ * Get message deleted flag value (from headers).
+ */
+ public function isDeleted(): bool
+ {
+ return 'D' === $this->getHeaders()->get('deleted');
+ }
+
+ /**
+ * Get message draft flag value (from headers).
+ */
+ public function isDraft(): bool
+ {
+ return 'X' === $this->getHeaders()->get('draft');
+ }
+
+ /**
+ * Has the message been marked as read?
+ */
+ public function isSeen(): bool
+ {
+ return 'N' !== $this->getHeaders()->get('recent') && 'U' !== $this->getHeaders()->get('unseen');
+ }
+
+ /**
+ * Mark message as seen.
+ *
+ * @deprecated since version 1.1, to be removed in 2.0
+ */
+ public function maskAsSeen(): bool
+ {
+ \trigger_error(\sprintf('%s is deprecated and will be removed in 2.0. Use %s::markAsSeen instead.', __METHOD__, __CLASS__), \E_USER_DEPRECATED);
+
+ return $this->markAsSeen();
+ }
+
+ /**
+ * Mark message as seen.
+ */
+ public function markAsSeen(): bool
+ {
+ return $this->setFlag('\\Seen');
+ }
+
+ /**
+ * Move message to another mailbox.
+ *
+ * @throws MessageCopyException
+ */
+ public function copy(MailboxInterface $mailbox): void
+ {
+ // 'deleted' header changed, force to reload headers, would be better to set deleted flag to true on header
+ $this->clearHeaders();
+
+ if (!\imap_mail_copy($this->resource->getStream(), (string) $this->getNumber(), $mailbox->getEncodedName(), \CP_UID)) {
+ throw new MessageCopyException(\sprintf('Message "%s" cannot be copied to "%s"', $this->getNumber(), $mailbox->getName()));
+ }
+ }
+
+ /**
+ * Move message to another mailbox.
+ *
+ * @throws MessageMoveException
+ */
+ public function move(MailboxInterface $mailbox): void
+ {
+ // 'deleted' header changed, force to reload headers, would be better to set deleted flag to true on header
+ $this->clearHeaders();
+
+ if (!\imap_mail_move($this->resource->getStream(), (string) $this->getNumber(), $mailbox->getEncodedName(), \CP_UID)) {
+ throw new MessageMoveException(\sprintf('Message "%s" cannot be moved to "%s"', $this->getNumber(), $mailbox->getName()));
+ }
+ }
+
+ /**
+ * Delete message.
+ *
+ * @throws MessageDeleteException
+ */
+ public function delete(): void
+ {
+ // 'deleted' header changed, force to reload headers, would be better to set deleted flag to true on header
+ $this->clearHeaders();
+
+ if (!\imap_delete($this->resource->getStream(), $this->getNumber(), \FT_UID)) {
+ throw new MessageDeleteException(\sprintf('Message "%s" cannot be deleted', $this->getNumber()));
+ }
+ }
+
+ /**
+ * 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.
+ *
+ * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
+ */
+ public function setFlag(string $flag): bool
+ {
+ $result = \imap_setflag_full($this->resource->getStream(), (string) $this->getNumber(), $flag, \ST_UID);
+
+ $this->clearHeaders();
+
+ return $result;
+ }
+
+ /**
+ * Clear Flag Message.
+ *
+ * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
+ */
+ public function clearFlag(string $flag): bool
+ {
+ $result = \imap_clearflag_full($this->resource->getStream(), (string) $this->getNumber(), $flag, \ST_UID);
+
+ $this->clearHeaders();
+
+ return $result;
+ }
+}