Skip to content

Commit 022fafd

Browse files
committed
Extract duplicated attachment retrieval
1 parent 84ed09d commit 022fafd

File tree

3 files changed

+63
-88
lines changed

3 files changed

+63
-88
lines changed

src/Attachment.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
namespace DirectoryTree\ImapEngine;
44

5+
use GuzzleHttp\Psr7\Utils;
56
use Illuminate\Contracts\Support\Arrayable;
67
use JsonSerializable;
78
use Psr\Http\Message\StreamInterface;
89
use Symfony\Component\Mime\MimeTypes;
10+
use ZBateson\MailMimeParser\Message\IMessagePart;
911

1012
class Attachment implements Arrayable, JsonSerializable
1113
{
@@ -20,6 +22,64 @@ public function __construct(
2022
protected StreamInterface $contentStream,
2123
) {}
2224

25+
/**
26+
* Get attachments from a parsed message.
27+
*
28+
* @return Attachment[]
29+
*/
30+
public static function parsed(MessageInterface $message): array
31+
{
32+
$attachments = [];
33+
34+
foreach ($message->parse()->getAllAttachmentParts() as $part) {
35+
if (static::isForwardedMessage($part)) {
36+
$attachments = array_merge($attachments, (new FileMessage($part->getContent()))->attachments());
37+
} else {
38+
$attachments[] = new Attachment(
39+
$part->getFilename(),
40+
$part->getContentId(),
41+
$part->getContentType(),
42+
$part->getContentDisposition(),
43+
$part->getBinaryContentStream() ?? Utils::streamFor(''),
44+
);
45+
}
46+
}
47+
48+
return $attachments;
49+
}
50+
51+
/**
52+
* Get attachments from a message's body structure using lazy streams.
53+
*
54+
* @return Attachment[]
55+
*/
56+
public static function lazy(Message $message): array
57+
{
58+
$attachments = [];
59+
60+
foreach ($message->bodyStructure(fetch: true)?->attachments() ?? [] as $part) {
61+
$attachments[] = new Attachment(
62+
$part->filename(),
63+
$part->id(),
64+
$part->contentType(),
65+
$part->disposition()?->type()?->value,
66+
new Support\LazyBodyPartStream($message, $part),
67+
);
68+
}
69+
70+
return $attachments;
71+
}
72+
73+
/**
74+
* Determine if the attachment should be treated as an embedded forwarded message.
75+
*/
76+
protected static function isForwardedMessage(IMessagePart $part): bool
77+
{
78+
return empty($part->getFilename())
79+
&& strtolower((string) $part->getContentType()) === 'message/rfc822'
80+
&& strtolower((string) $part->getContentDisposition()) !== 'attachment';
81+
}
82+
2383
/**
2484
* Get the attachment's filename.
2585
*/

src/HasMessageAccessors.php

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@
44

55
use Carbon\Carbon;
66
use Carbon\CarbonInterface;
7-
use GuzzleHttp\Psr7\Utils;
87
use ZBateson\MailMimeParser\Header\DateHeader;
98
use ZBateson\MailMimeParser\Header\HeaderConsts;
109
use ZBateson\MailMimeParser\Header\IHeader;
1110
use ZBateson\MailMimeParser\Header\IHeaderPart;
1211
use ZBateson\MailMimeParser\IMessage;
13-
use ZBateson\MailMimeParser\Message\IMessagePart;
1412

1513
trait HasMessageAccessors
1614
{
@@ -158,23 +156,7 @@ public function text(): ?string
158156
*/
159157
public function attachments(): array
160158
{
161-
$attachments = [];
162-
163-
foreach ($this->parse()->getAllAttachmentParts() as $part) {
164-
if ($this->isForwardedMessage($part)) {
165-
$attachments = array_merge($attachments, (new FileMessage($part->getContent()))->attachments());
166-
} else {
167-
$attachments[] = new Attachment(
168-
$part->getFilename(),
169-
$part->getContentId(),
170-
$part->getContentType(),
171-
$part->getContentDisposition(),
172-
$part->getBinaryContentStream() ?? Utils::streamFor(''),
173-
);
174-
}
175-
}
176-
177-
return $attachments;
159+
return Attachment::parsed($this);
178160
}
179161

180162
/**
@@ -192,14 +174,4 @@ public function attachmentCount(): int
192174
{
193175
return $this->parse()->getAttachmentCount();
194176
}
195-
196-
/**
197-
* Determine if the attachment should be treated as an embedded forwarded message.
198-
*/
199-
protected function isForwardedMessage(IMessagePart $part): bool
200-
{
201-
return empty($part->getFilename())
202-
&& strtolower((string) $part->getContentType()) === 'message/rfc822'
203-
&& strtolower((string) $part->getContentDisposition()) !== 'attachment';
204-
}
205177
}

src/Message.php

Lines changed: 2 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use DirectoryTree\ImapEngine\Connection\Responses\MessageResponseParser;
1010
use DirectoryTree\ImapEngine\Exceptions\ImapCapabilityException;
1111
use DirectoryTree\ImapEngine\Support\Str;
12-
use GuzzleHttp\Psr7\Utils;
1312
use Illuminate\Contracts\Support\Arrayable;
1413
use JsonSerializable;
1514
use ZBateson\MailMimeParser\Header\DateHeader;
@@ -19,7 +18,6 @@
1918
use ZBateson\MailMimeParser\Header\Part\AddressPart;
2019
use ZBateson\MailMimeParser\Header\Part\ContainerPart;
2120
use ZBateson\MailMimeParser\Header\Part\NameValuePart;
22-
use ZBateson\MailMimeParser\Message\IMessagePart;
2321

2422
class Message implements Arrayable, JsonSerializable, MessageInterface
2523
{
@@ -420,59 +418,14 @@ public function html(bool $fetch = false): ?string
420418
public function attachments(bool $fetch = false): array
421419
{
422420
if ($fetch && ! $this->hasBody()) {
423-
return $this->getAttachmentsFromBodyStructure();
421+
return Attachment::lazy($this);
424422
}
425423

426424
if ($this->isEmpty()) {
427425
return [];
428426
}
429427

430-
return $this->getParsedAttachments();
431-
}
432-
433-
/**
434-
* Get attachments from the body structure.
435-
*
436-
* @return Attachment[]
437-
*/
438-
protected function getAttachmentsFromBodyStructure(): array
439-
{
440-
return array_map(
441-
fn (BodyStructurePart $part) => new Attachment(
442-
$part->filename(),
443-
$part->id(),
444-
$part->contentType(),
445-
$part->disposition()?->type()?->value,
446-
new Support\LazyBodyPartStream($this, $part),
447-
),
448-
$this->bodyStructure(fetch: true)?->attachments() ?? []
449-
);
450-
}
451-
452-
/**
453-
* Get attachments from the parsed message.
454-
*
455-
* @return Attachment[]
456-
*/
457-
protected function getParsedAttachments(): array
458-
{
459-
$attachments = [];
460-
461-
foreach ($this->parse()->getAllAttachmentParts() as $part) {
462-
if ($this->isForwardedMessage($part)) {
463-
$attachments = array_merge($attachments, (new FileMessage($part->getContent()))->attachments());
464-
} else {
465-
$attachments[] = new Attachment(
466-
$part->getFilename(),
467-
$part->getContentId(),
468-
$part->getContentType(),
469-
$part->getContentDisposition(),
470-
$part->getBinaryContentStream() ?? Utils::streamFor(''),
471-
);
472-
}
473-
}
474-
475-
return $attachments;
428+
return Attachment::parsed($this);
476429
}
477430

478431
/**
@@ -495,16 +448,6 @@ public function attachmentCount(): int
495448
return $this->parse()->getAttachmentCount();
496449
}
497450

498-
/**
499-
* Determine if the attachment should be treated as an embedded forwarded message.
500-
*/
501-
protected function isForwardedMessage(IMessagePart $part): bool
502-
{
503-
return empty($part->getFilename())
504-
&& strtolower((string) $part->getContentType()) === 'message/rfc822'
505-
&& strtolower((string) $part->getContentDisposition()) !== 'attachment';
506-
}
507-
508451
/**
509452
* Fetch a specific body part by part number.
510453
*/

0 commit comments

Comments
 (0)