Skip to content

Commit

Permalink
Messages: Add ability to native save mail content to file (#556)
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubboucek authored Feb 16, 2023
1 parent a238641 commit 92647fd
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ public function getRawMessage(): string
return $this->rawMessage;
}

/**
* @param resource|string $file the path to the saved file as a string, or a valid file descriptor
*/
public function saveRawMessage($file): void
{
$this->doSaveContent($file, '');
}

public function getHeaders(): Message\Headers
{
if (null === $this->headers) {
Expand Down
20 changes: 20 additions & 0 deletions src/Message/AbstractPart.php
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,26 @@ final protected function doGetContent(string $partNumber): string
return $return;
}

/**
* Save raw message content to file.
*
* @param resource|string $file the path to the saved file as a string, or a valid file descriptor
*/
final protected function doSaveContent($file, string $partNumber): void
{
$return = \imap_savebody(
$this->resource->getStream(),
$file,
$this->getNumber(),
$partNumber,
\FT_UID | \FT_PEEK
);

if (false === $return) {
throw new ImapFetchbodyException('imap_savebody failed');
}
}

final public function getParts(): array
{
$this->lazyParseStructure();
Expand Down
7 changes: 7 additions & 0 deletions src/Message/BasicMessageInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ public function getRawHeaders(): string;
*/
public function getRawMessage(): string;

/**
* Save the raw message, including all headers, parts, etc. unencoded and unparsed to file.
*
* @param resource|string $file the path to the saved file as a string, or a valid file descriptor
*/
public function saveRawMessage($file): void;

/**
* Get message headers.
*/
Expand Down
8 changes: 8 additions & 0 deletions src/Message/EmbeddedMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ public function getRawMessage(): string
return $this->rawMessage;
}

/**
* @param resource|string $file the path to the saved file as a string, or a valid file descriptor
*/
public function saveRawMessage($file): void
{
$this->doSaveContent($file, $this->getPartNumber());
}

/**
* Get content part number.
*/
Expand Down
28 changes: 28 additions & 0 deletions tests/EmbeddedMessageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,32 @@ public function testEmbeddedMessageWithoutContentDisposition(): void
static::assertNotEmpty($attachment->getContent());
static::assertSame('file4.zip', $attachment->getFilename());
}

public function testSaveEmbeddedMessage(): void
{
$mailbox = $this->createMailbox();
$raw = $this->getFixture('embedded_email_without_content_disposition');
$mailbox->addMessage($raw);

$message = $mailbox->getMessage(1);
$attachments = $message->getAttachments();

// skip 1. non-embedded attachment (file.jpg) to embedded one
$attachment = \next($attachments);
static::assertNotFalse($attachment);
static::assertTrue($attachment->isEmbeddedMessage());

$embeddedMessage = $attachment->getEmbeddedMessage();

$file = \fopen('php://temp', 'w+');
if (false === $file) {
static::fail('Unable to create temporary file stream');
}

$embeddedMessage->saveRawMessage($file);
\fseek($file, 0);

$rawEmbedded = $this->getFixture('embedded_email_without_content_disposition-embedded');
static::assertSame($rawEmbedded, \stream_get_contents($file));
}
}
39 changes: 39 additions & 0 deletions tests/MessageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,45 @@ public function testGetRawMessage(): void
static::assertSame($fixture, $message->getRawMessage());
}

public function testSaveFileRawMessage(): void
{
$fixture = $this->getFixture('structured_with_attachment');
$this->mailbox->addMessage($fixture);

$message = $this->mailbox->getMessage(1);

$filename = \tempnam(\sys_get_temp_dir(), 'testSaveFileRawMessage');
if (false === $filename) {
static::fail('Unable to create temporary file');
}

$message->saveRawMessage($filename);

static::assertSame($fixture, \file_get_contents($filename));

\unlink($filename);
}

public function testSaveResourceRawMessage(): void
{
$fixture = $this->getFixture('structured_with_attachment');
$this->mailbox->addMessage($fixture);

$message = $this->mailbox->getMessage(1);

$file = \fopen('php://temp', 'w+');
if (false === $file) {
static::fail('Unable to create temporary file stream');
}

$message->saveRawMessage($file);
\fseek($file, 0);

static::assertSame($fixture, \stream_get_contents($file));

\fclose($file);
}

public function testAttachmentOnlyEmail(): void
{
$fixture = $this->getFixture('mail_that_is_attachment');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
Received: from webmail.my-office.cz (localhost [127.0.0.1])
by keira.cofis.cz
; Fri, 29 Jan 2016 14:25:40 +0100
From: [email protected]
To: [email protected]
Date: Fri, 5 Apr 2019 12:10:49 +0200
Subject: embedded_message_subject
Message-ID: <[email protected]>
Accept-Language: pl-PL, nl-NL
Content-Language: pl-PL
Content-Type: multipart/mixed;
boundary="_005_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_"
MIME-Version: 1.0

--_005_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_
Content-Type: multipart/alternative;
boundary="_000_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_"
--_000_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_
Content-Type: text/plain; charset="iso-8859-2"
Content-Transfer-Encoding: quoted-printable
some txt
--_000_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_
Content-Type: text/html; charset="iso-8859-2"
Content-Transfer-Encoding: quoted-printable

<html>
<p>some txt</p>
</html>

--_000_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_--

--_005_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;
name="file1.xlsx"
Content-Description: file1.xlsx
Content-Disposition: attachment; filename="file1.xlsx"; size=29;
creation-date="Fri, 05 Apr 2019 10:06:01 GMT";
modification-date="Fri, 05 Apr 2019 10:10:49 GMT"
Content-Transfer-Encoding: base64
IHRoaXMgaXMgY29udGVudCBvZiB0ZXN0IGZpbGU=
--_005_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;
name="file2.xlsx"
Content-Description: file2
Content-Disposition: attachment; filename="file2.xlsx"; size=29;
creation-date="Fri, 05 Apr 2019 10:10:19 GMT";
modification-date="Wed, 03 Apr 2019 11:04:32 GMT"
Content-Transfer-Encoding: base64
IHRoaXMgaXMgY29udGVudCBvZiB0ZXN0IGZpbGU=
--_005_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_--

0 comments on commit 92647fd

Please sign in to comment.