diff --git a/CHANGELOG.md b/CHANGELOG.md index b5035414..62ea0d92 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) princip - NaN ### Added -- NaN +- sizes() methods to protocol interface and implmentations (to have FETCH NNN RFC822.SIZE attribute available) ### Breaking changes - NaN diff --git a/examples/size_test.php b/examples/size_test.php new file mode 100644 index 00000000..44f832c5 --- /dev/null +++ b/examples/size_test.php @@ -0,0 +1,83 @@ + 'toFill', + 'port' => 993, + 'encryption' => 'ssl', + 'validate_cert' => true, + 'username' => 'toFill', + 'password' => 'toFill', + 'protocol' => 'imap' +); +set_include_path('/home/didi1357/git/php-imap/src'); + + +ini_set('display_errors', 1); +ini_set('display_startup_errors', 1); +error_reporting(E_ALL); + +require_once 'IMAP.php'; +require_once 'Traits/HasEvents.php'; +require_once 'Exceptions/MaskNotFoundException.php'; +require_once 'Client.php'; +require_once 'ClientManager.php'; +require_once 'Support/Masks/Mask.php'; +require_once 'Support/Masks/MessageMask.php'; +require_once 'Support/Masks/AttachmentMask.php'; +require_once 'Connection/Protocols/Response.php'; +require_once 'Connection/Protocols/ProtocolInterface.php'; +require_once 'Connection/Protocols/Protocol.php'; +require_once 'Connection/Protocols/ImapProtocol.php'; +require_once '../tests/vendor/autoload.php'; +require_once 'Support/PaginatedCollection.php'; +require_once 'Support/FolderCollection.php'; +require_once 'Folder.php'; +require_once 'Exceptions/ResponseException.php'; +require_once 'Query/Query.php'; +require_once 'Query/WhereQuery.php'; +require_once 'Support/MessageCollection.php'; +require_once 'Support/FlagCollection.php'; +require_once 'Support/AttachmentCollection.php'; +require_once 'Part.php'; +require_once 'Structure.php'; +require_once 'Attribute.php'; +require_once 'Address.php'; +require_once 'EncodingAliases.php'; +require_once 'Header.php'; +require_once 'Message.php'; + +use Webklex\PHPIMAP\ClientManager; +use Webklex\PHPIMAP\Support\Masks\MessageMask; +use Webklex\PHPIMAP\Support\Masks\AttachmentMask; + +$CONFIG['masks'] = array( + 'message' => MessageMask::class, + 'attachment' => AttachmentMask::class +); +echo "
"; +$cm = new ClientManager($options = []); +$client = $cm->make($CONFIG)->connect(); +//$client->getConnection()->enableDebug(); // uncomment this for debug output! +$folder = $client->getFolderByPath('INBOX'); +//$message = $folder->messages()->getMessageByMsgn(1); // did not work as msgn implementation is currently broken! +$message = $folder->messages()->getMessageByUid(2); +var_dump($message->getSize()); + + +?> + diff --git a/src/Connection/Protocols/ImapProtocol.php b/src/Connection/Protocols/ImapProtocol.php index fc23c56f..07ea3f6d 100644 --- a/src/Connection/Protocols/ImapProtocol.php +++ b/src/Connection/Protocols/ImapProtocol.php @@ -698,7 +698,7 @@ public function fetch(array|string $items, array|int $from, mixed $to = null, in // if we want only one message we can ignore everything else and just return if ($to === null && !is_array($from) && ($uid === IMAP::ST_UID ? $tokens[2][$uidKey] == $from : $tokens[0] == $from)) { // we still need to read all lines - while (!$this->readLine($response, $tokens, $tag)) + if (!$this->readLine($response, $tokens, $tag)) return $response->setResult($data); } if ($uid === IMAP::ST_UID) { @@ -756,6 +756,19 @@ public function flags(int|array $uids, int|string $uid = IMAP::ST_UID): Response return $this->fetch(["FLAGS"], $uids, null, $uid); } + /** + * Fetch message sizes + * @param int|array $uids + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return Response + * @throws RuntimeException + */ + public function sizes(int|array $uids, int|string $uid = IMAP::ST_UID): Response { + return $this->fetch(["RFC822.SIZE"], $uids, null, $uid); + } + /** * Get uid for a given id * @param int|null $id message number diff --git a/src/Connection/Protocols/LegacyProtocol.php b/src/Connection/Protocols/LegacyProtocol.php index b515d255..65c5342d 100644 --- a/src/Connection/Protocols/LegacyProtocol.php +++ b/src/Connection/Protocols/LegacyProtocol.php @@ -314,6 +314,34 @@ public function flags(int|array $uids, int|string $uid = IMAP::ST_UID): Response return $result; }); } + + /** + * Fetch message sizes + * @param int|array $uids + * @param int|string $uid set to IMAP::ST_UID if you pass message unique identifiers instead of numbers. + * + * @return Response + */ + public function sizes(int|array $uids, int|string $uid = IMAP::ST_UID): Response { + return $this->response()->wrap(function($response)use($uids, $uid){ + /** @var Response $response */ + $result = []; + $uids = is_array($uids) ? $uids : [$uids]; + $uid_text = implode("','",$uids); + $response->addCommand("imap_fetch_overview"); + $raw_overview = false; + if ($uid == IMAP::ST_UID) + $raw_overview = imap_fetch_overview($this->stream, $uid_text, FT_UID); + else + $raw_overview = imap_fetch_overview($this->stream, $uid_text); + if ($raw_overview !== false) { + foreach ($raw_overview as $overview_element) { + $result[$overview_element[$uid == IMAP::ST_UID ? 'uid': 'msgno']] = $overview_element['size']; + } + } + return $result; + }); + } /** * Get uid for a given id diff --git a/src/Connection/Protocols/ProtocolInterface.php b/src/Connection/Protocols/ProtocolInterface.php index 0093e513..c02d7800 100644 --- a/src/Connection/Protocols/ProtocolInterface.php +++ b/src/Connection/Protocols/ProtocolInterface.php @@ -151,6 +151,17 @@ public function headers(int|array $uids, string $rfc = "RFC822", int|string $uid * @throws RuntimeException */ public function flags(int|array $uids, int|string $uid = IMAP::ST_UID): Response; + + /** + * Fetch message sizes + * @param int|array $uids + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return Response + * @throws RuntimeException + */ + public function sizes(int|array $uids, int|string $uid = IMAP::ST_UID): Response; /** * Get uid for a given id diff --git a/src/Exceptions/MessageSizeFetchingException.php b/src/Exceptions/MessageSizeFetchingException.php new file mode 100644 index 00000000..f14fce51 --- /dev/null +++ b/src/Exceptions/MessageSizeFetchingException.php @@ -0,0 +1,24 @@ +attributes[$name] = $this->client->getConnection()->getMessageNumber($this->uid)->validate()->integer(); return $this->attributes[$name]; + case "size": + if (!isset($this->attributes[$name])) { + $this->fetchSize(); + } + return $this->attributes[$name]; } return $this->header->get($name); @@ -592,6 +597,20 @@ public function parseBody(): Message { return $body; } + + /** + * Fetches the size for this message. + * + * @throws MessageSizeFetchingException + */ + private function fetchSize(): void { + $sequence_id = $this->getSequenceId(); + $sizes = $this->client->getConnection()->sizes([$sequence_id], $this->sequence)->validatedData(); + if (!isset($sizes[$sequence_id])) { + throw new MessageSizeFetchingException("sizes did not set an array entry for the supplied sequence_id", 0); + } + $this->attributes["size"] = $sizes[$sequence_id]; + } /** * Handle auto "Seen" flag handling @@ -1301,6 +1320,15 @@ public function getHeader(): ?Header { return $this->header; } + /** + * Get the message size in bytes + * + * @return int Size of the message in bytes + */ + public function getSize(): int { + return $this->get("size"); + } + /** * Get the current client * @@ -1565,7 +1593,7 @@ public function getSequence(): int { } /** - * Set the sequence type + * Get the current sequence id (either a UID or a message number!) * * @return int */