Skip to content

Commit f950cb9

Browse files
authored
Merge pull request #49 from DirectoryTree/extract-message-response-parsing
Extract message response parsing into class
2 parents 6b00072 + 54fd7aa commit f950cb9

File tree

3 files changed

+149
-33
lines changed

3 files changed

+149
-33
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
namespace DirectoryTree\ImapEngine\Connection\Responses;
4+
5+
class MessageResponseParser
6+
{
7+
/**
8+
* Get the flags from an untagged response.
9+
*
10+
* @return array<string, string[]>
11+
*/
12+
public static function getFlags(UntaggedResponse $response): array
13+
{
14+
$data = $response->tokenAt(3);
15+
16+
$uid = $data->lookup('UID')->value;
17+
$flags = $data->lookup('FLAGS')->values();
18+
19+
return [$uid => $flags];
20+
}
21+
22+
/**
23+
* Get the body header from an untagged response.
24+
*
25+
* @return array<string, string>
26+
*/
27+
public static function getBodyHeader(UntaggedResponse $response): array
28+
{
29+
$data = $response->tokenAt(3);
30+
31+
$uid = $data->lookup('UID')->value;
32+
$headers = $data->lookup('[HEADER]')->value;
33+
34+
return [$uid => $headers];
35+
}
36+
37+
/**
38+
* Get the body text from an untagged response.
39+
*
40+
* @return array<string, string>
41+
*/
42+
public static function getBodyText(UntaggedResponse $response): array
43+
{
44+
$data = $response->tokenAt(3);
45+
46+
$uid = $data->lookup('UID')->value;
47+
$contents = $data->lookup('[TEXT]')->value;
48+
49+
return [$uid => $contents];
50+
}
51+
}

src/MessageQuery.php

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use DirectoryTree\ImapEngine\Collections\ResponseCollection;
77
use DirectoryTree\ImapEngine\Connection\ConnectionInterface;
88
use DirectoryTree\ImapEngine\Connection\ImapQueryBuilder;
9+
use DirectoryTree\ImapEngine\Connection\Responses\MessageResponseParser;
910
use DirectoryTree\ImapEngine\Connection\Responses\UntaggedResponse;
1011
use DirectoryTree\ImapEngine\Connection\Tokens\Atom;
1112
use DirectoryTree\ImapEngine\Enums\ImapFetchIdentifier;
@@ -337,36 +338,15 @@ protected function fetch(Collection $messages): array
337338

338339
$flags = $this->fetchFlags ? $this->connection()
339340
->flags($uids)
340-
->mapWithKeys(function (UntaggedResponse $response) {
341-
$data = $response->tokenAt(3);
342-
343-
$uid = $data->lookup('UID')->value;
344-
$flags = $data->lookup('FLAGS')->values();
345-
346-
return [$uid => $flags];
347-
}) : new Collection;
341+
->mapWithKeys(MessageResponseParser::getFlags(...))->all() : [];
348342

349343
$headers = $this->fetchHeaders ? $this->connection()
350344
->bodyHeader($uids, $this->fetchAsUnread)
351-
->mapWithKeys(function (UntaggedResponse $response) {
352-
$data = $response->tokenAt(3);
353-
354-
$uid = $data->lookup('UID')->value;
355-
$headers = $data->lookup('[HEADER]')->value;
356-
357-
return [$uid => $headers];
358-
}) : new Collection;
345+
->mapWithKeys(MessageResponseParser::getBodyHeader(...))->all() : [];
359346

360347
$contents = $this->fetchBody ? $this->connection()
361348
->bodyText($uids, $this->fetchAsUnread)
362-
->mapWithKeys(function (UntaggedResponse $response) {
363-
$data = $response->tokenAt(3);
364-
365-
$uid = $data->lookup('UID')->value;
366-
$contents = $data->lookup('[TEXT]')->value;
367-
368-
return [$uid => $contents];
369-
}) : new Collection;
349+
->mapWithKeys(MessageResponseParser::getBodyText(...))->all() : [];
370350

371351
return [
372352
'uids' => $uids,
@@ -381,13 +361,7 @@ protected function fetch(Collection $messages): array
381361
*/
382362
protected function newMessage(int $uid, array $flags, string $headers, string $contents): Message
383363
{
384-
return new Message(
385-
$this->folder,
386-
$uid,
387-
$flags,
388-
$headers,
389-
$contents,
390-
);
364+
return new Message($this->folder, $uid, $flags, $headers, $contents);
391365
}
392366

393367
/**
@@ -459,11 +433,11 @@ public function get(): MessageCollection
459433
*/
460434
public function append(string $message, mixed $flags = null): int
461435
{
462-
$result = $this->connection()->append(
436+
$response = $this->connection()->append(
463437
$this->folder->path(), $message, Str::enums($flags),
464438
);
465439

466-
return $result // TAG4 OK [APPENDUID <uidvalidity> <uid>] APPEND completed.
440+
return $response // TAG4 OK [APPENDUID <uidvalidity> <uid>] APPEND completed.
467441
->tokenAt(2) // [APPENDUID <uidvalidity> <uid>]
468442
->tokenAt(2) // <uid>
469443
->value;
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
3+
use DirectoryTree\ImapEngine\Connection\Responses\Data\ListData;
4+
use DirectoryTree\ImapEngine\Connection\Responses\MessageResponseParser;
5+
use DirectoryTree\ImapEngine\Connection\Responses\UntaggedResponse;
6+
use DirectoryTree\ImapEngine\Connection\Tokens\Atom;
7+
use DirectoryTree\ImapEngine\Connection\Tokens\Literal;
8+
9+
it('parses flags from untagged response', function () {
10+
$response = new UntaggedResponse([
11+
new Atom('*'), // Untagged marker
12+
new Atom('1'), // Sequence number (example)
13+
new Atom('FETCH'), // Command type
14+
new ListData([ // Data list
15+
new Atom('UID'),
16+
new Atom('12345'), // The message UID
17+
new Atom('FLAGS'),
18+
new ListData([ // The list of flags
19+
new Atom('\Seen'),
20+
new Atom('\Answered'),
21+
new Atom('$Important'), // Example custom flag
22+
]),
23+
]),
24+
]);
25+
26+
$parsedFlags = MessageResponseParser::getFlags($response);
27+
28+
expect($parsedFlags)->toBe([
29+
'12345' => ['\Seen', '\Answered', '$Important'],
30+
]);
31+
});
32+
33+
it('parses body header from untagged response', function () {
34+
$headerContent = "From: [email protected]\r\nTo: [email protected]\r\nSubject: Test Email Header\r\n";
35+
36+
$response = new UntaggedResponse([
37+
new Atom('*'), // Untagged marker
38+
new Atom('2'), // Sequence number (example)
39+
new Atom('FETCH'), // Command type
40+
new ListData([ // Data list
41+
new Atom('UID'),
42+
new Atom('54321'), // The message UID
43+
new Atom('BODY'),
44+
new Atom('[HEADER]'), // Specifies header part
45+
new Literal($headerContent), // The header content as a literal
46+
]),
47+
]);
48+
49+
$parsedHeader = MessageResponseParser::getBodyHeader($response); //
50+
51+
expect($parsedHeader)->toBe(['54321' => $headerContent]);
52+
});
53+
54+
it('parses body text from untagged response', function () {
55+
$textContent = "This is the plain text body of the email.\r\nIt might have multiple lines.\r\n";
56+
57+
$response = new UntaggedResponse([
58+
new Atom('*'), // Untagged marker
59+
new Atom('3'), // Sequence number (example)
60+
new Atom('FETCH'), // Command type
61+
new ListData([ // Data list
62+
new Atom('UID'),
63+
new Atom('98765'), // The message UID
64+
new Atom('BODY'),
65+
new Atom('[TEXT]'), // Specifies text part
66+
new Literal($textContent), // The text content as a literal
67+
]),
68+
]);
69+
70+
$parsedText = MessageResponseParser::getBodyText($response);
71+
72+
expect($parsedText)->toBe(['98765' => $textContent]);
73+
});
74+
75+
it('handles empty flags list correctly', function () {
76+
$response = new UntaggedResponse([
77+
new Atom('*'),
78+
new Atom('4'),
79+
new Atom('FETCH'),
80+
new ListData([
81+
new Atom('UID'),
82+
new Atom('11111'),
83+
new Atom('FLAGS'),
84+
new ListData([]), // Empty flags list
85+
]),
86+
]);
87+
88+
$parsedFlags = MessageResponseParser::getFlags($response);
89+
90+
expect($parsedFlags)->toBe(['11111' => []]);
91+
});

0 commit comments

Comments
 (0)