|
12 | 12 | use DirectoryTree\ImapEngine\Connection\Tokens\Token; |
13 | 13 | use DirectoryTree\ImapEngine\Enums\ImapFetchIdentifier; |
14 | 14 | use DirectoryTree\ImapEngine\Enums\ImapFlag; |
| 15 | +use DirectoryTree\ImapEngine\Exceptions\ImapCapabilityException; |
15 | 16 | use DirectoryTree\ImapEngine\Exceptions\ImapCommandException; |
16 | 17 | use DirectoryTree\ImapEngine\Exceptions\RuntimeException; |
17 | 18 | use DirectoryTree\ImapEngine\Pagination\LengthAwarePaginator; |
@@ -67,7 +68,7 @@ public function firstOrFail(): MessageInterface |
67 | 68 | */ |
68 | 69 | public function get(): MessageCollection |
69 | 70 | { |
70 | | - return $this->process($this->search()); |
| 71 | + return $this->process($this->sortKey ? $this->sort() : $this->search()); |
71 | 72 | } |
72 | 73 |
|
73 | 74 | /** |
@@ -354,10 +355,15 @@ protected function populate(Collection $uids): MessageCollection |
354 | 355 | */ |
355 | 356 | protected function fetch(Collection $messages): array |
356 | 357 | { |
357 | | - $messages = match ($this->fetchOrder) { |
358 | | - 'asc' => $messages->sort(SORT_NUMERIC), |
359 | | - 'desc' => $messages->sortDesc(SORT_NUMERIC), |
360 | | - }; |
| 358 | + // Only apply client-side sorting when not using server-side sorting. |
| 359 | + // When sortKey is set, the IMAP SORT command already returns UIDs |
| 360 | + // in the correct order, so we should preserve that order. |
| 361 | + if (! $this->sortKey) { |
| 362 | + $messages = match ($this->fetchOrder) { |
| 363 | + 'asc' => $messages->sort(SORT_NUMERIC), |
| 364 | + 'desc' => $messages->sortDesc(SORT_NUMERIC), |
| 365 | + }; |
| 366 | + } |
361 | 367 |
|
362 | 368 | $uids = $messages->forPage($this->page, $this->limit)->values(); |
363 | 369 |
|
@@ -446,6 +452,33 @@ protected function search(): Collection |
446 | 452 | )); |
447 | 453 | } |
448 | 454 |
|
| 455 | + /** |
| 456 | + * Execute an IMAP UID SORT request using RFC 5256. |
| 457 | + */ |
| 458 | + protected function sort(): Collection |
| 459 | + { |
| 460 | + if (! in_array('SORT', $this->folder->mailbox()->capabilities())) { |
| 461 | + throw new ImapCapabilityException( |
| 462 | + 'Unable to sort messages. IMAP server does not support SORT capability.' |
| 463 | + ); |
| 464 | + } |
| 465 | + |
| 466 | + if ($this->query->isEmpty()) { |
| 467 | + $this->query->all(); |
| 468 | + } |
| 469 | + |
| 470 | + $response = $this->connection()->sort( |
| 471 | + $this->sortKey, |
| 472 | + $this->sortDirection, |
| 473 | + [$this->query->toImap()] |
| 474 | + ); |
| 475 | + |
| 476 | + return new Collection(array_map( |
| 477 | + fn (Token $token) => $token->value, |
| 478 | + $response->tokensAfter(2) |
| 479 | + )); |
| 480 | + } |
| 481 | + |
449 | 482 | /** |
450 | 483 | * Get the UID for the given identifier. |
451 | 484 | */ |
|
0 commit comments