mirror of
https://github.com/itflow-org/itflow
synced 2026-09-09 16:25:11 +00:00
179 lines
4.4 KiB
PHP
179 lines
4.4 KiB
PHP
<?php
|
|
|
|
namespace DirectoryTree\ImapEngine;
|
|
|
|
use GuzzleHttp\Psr7\Utils;
|
|
use Illuminate\Contracts\Support\Arrayable;
|
|
use JsonSerializable;
|
|
use Psr\Http\Message\StreamInterface;
|
|
use Symfony\Component\Mime\MimeTypes;
|
|
use ZBateson\MailMimeParser\Message\IMessagePart;
|
|
|
|
class Attachment implements Arrayable, JsonSerializable
|
|
{
|
|
/**
|
|
* Constructor.
|
|
*/
|
|
public function __construct(
|
|
protected ?string $filename,
|
|
protected ?string $contentId,
|
|
protected string $contentType,
|
|
protected ?string $contentDisposition,
|
|
protected StreamInterface $contentStream,
|
|
) {}
|
|
|
|
/**
|
|
* Get attachments from a parsed message.
|
|
*
|
|
* @return Attachment[]
|
|
*/
|
|
public static function parsed(MessageInterface $message): array
|
|
{
|
|
$attachments = [];
|
|
|
|
foreach ($message->parse()->getAllAttachmentParts() as $part) {
|
|
if (static::isForwardedMessage($part)) {
|
|
$attachments = array_merge($attachments, (new FileMessage($part->getContent()))->attachments());
|
|
} else {
|
|
$attachments[] = new Attachment(
|
|
$part->getFilename(),
|
|
$part->getContentId(),
|
|
$part->getContentType(),
|
|
$part->getContentDisposition(),
|
|
$part->getBinaryContentStream() ?? Utils::streamFor(''),
|
|
);
|
|
}
|
|
}
|
|
|
|
return $attachments;
|
|
}
|
|
|
|
/**
|
|
* Get attachments from a message's body structure using lazy streams.
|
|
*
|
|
* @return Attachment[]
|
|
*/
|
|
public static function lazy(Message $message): array
|
|
{
|
|
$attachments = [];
|
|
|
|
foreach ($message->bodyStructure(fetch: true)?->attachments() ?? [] as $part) {
|
|
$attachments[] = new Attachment(
|
|
$part->filename(),
|
|
$part->id(),
|
|
$part->contentType(),
|
|
$part->disposition()?->type()?->value,
|
|
new Support\LazyBodyPartStream($message, $part),
|
|
);
|
|
}
|
|
|
|
return $attachments;
|
|
}
|
|
|
|
/**
|
|
* Determine if the attachment should be treated as an embedded forwarded message.
|
|
*/
|
|
protected static function isForwardedMessage(IMessagePart $part): bool
|
|
{
|
|
return empty($part->getFilename())
|
|
&& strtolower((string) $part->getContentType()) === 'message/rfc822'
|
|
&& strtolower((string) $part->getContentDisposition()) !== 'attachment';
|
|
}
|
|
|
|
/**
|
|
* Get the attachment's filename.
|
|
*/
|
|
public function filename(): ?string
|
|
{
|
|
return $this->filename;
|
|
}
|
|
|
|
/**
|
|
* Get the attachment's content ID.
|
|
*/
|
|
public function contentId(): ?string
|
|
{
|
|
return $this->contentId;
|
|
}
|
|
|
|
/**
|
|
* Get the attachment's content type.
|
|
*/
|
|
public function contentType(): string
|
|
{
|
|
return $this->contentType;
|
|
}
|
|
|
|
/**
|
|
* Get the attachment's content disposition.
|
|
*/
|
|
public function contentDisposition(): string
|
|
{
|
|
return $this->contentDisposition;
|
|
}
|
|
|
|
/**
|
|
* Get the attachment's contents.
|
|
*/
|
|
public function contents(): string
|
|
{
|
|
if ($this->contentStream->isSeekable()) {
|
|
$this->contentStream->rewind();
|
|
}
|
|
|
|
return $this->contentStream->getContents();
|
|
}
|
|
|
|
/**
|
|
* Get the attachment's content stream.
|
|
*/
|
|
public function contentStream(): StreamInterface
|
|
{
|
|
return $this->contentStream;
|
|
}
|
|
|
|
/**
|
|
* Save the attachment to a file.
|
|
*/
|
|
public function save(string $path): false|int
|
|
{
|
|
return file_put_contents($path, $this->contents());
|
|
}
|
|
|
|
/**
|
|
* Get the attachment's extension.
|
|
*/
|
|
public function extension(): ?string
|
|
{
|
|
if ($ext = pathinfo($this->filename ?? '', PATHINFO_EXTENSION)) {
|
|
return $ext;
|
|
}
|
|
|
|
if ($ext = (MimeTypes::getDefault()->getExtensions($this->contentType)[0] ?? null)) {
|
|
return $ext;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get the array representation of the attachment.
|
|
*/
|
|
public function toArray(): array
|
|
{
|
|
return [
|
|
'filename' => $this->filename,
|
|
'content_type' => $this->contentType,
|
|
'contents' => $this->contents(),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get the JSON representation of the attachment.
|
|
*/
|
|
public function jsonSerialize(): array
|
|
{
|
|
return $this->toArray();
|
|
}
|
|
}
|