Skip to content

Commit

Permalink
Merge pull request #222 from Slamdunk/plain_text_embedded
Browse files Browse the repository at this point in the history
Recursive Embedded email body bug
  • Loading branch information
Slamdunk authored Oct 3, 2017
2 parents 76da321 + c9febc2 commit a5aa591
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 23 deletions.
11 changes: 10 additions & 1 deletion src/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ final class Message extends Message\AbstractMessage implements MessageInterface
*/
private $rawHeaders;

/**
* @var null|string
*/
private $rawMessage;

/**
* Constructor.
*
Expand Down Expand Up @@ -84,7 +89,11 @@ public function getRawHeaders(): string
*/
public function getRawMessage(): string
{
return $this->doGetContent('');
if (null === $this->rawMessage) {
$this->rawMessage = $this->doGetContent('');
}

return $this->rawMessage;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/Message/AbstractMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ final public function getSubject()
/**
* Get body HTML.
*
* @return string | null Null if message has no HTML message part
* @return null|string
*/
final public function getBodyHtml()
{
Expand All @@ -148,7 +148,7 @@ final public function getBodyHtml()
/**
* Get body text.
*
* @return string
* @return null|string
*/
final public function getBodyText()
{
Expand Down
48 changes: 29 additions & 19 deletions src/Message/AbstractPart.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,15 +229,25 @@ final public function getParameters(): Parameters
*
* @return string
*/
public function getContent(): string
final public function getContent(): string
{
if (null === $this->content) {
$this->content = $this->doGetContent($this->partNumber);
$this->content = $this->doGetContent($this->getContentPartNumber());
}

return $this->content;
}

/**
* Get content part number.
*
* @return string
*/
protected function getContentPartNumber(): string
{
return $this->partNumber;
}

/**
* Get decoded part content.
*
Expand Down Expand Up @@ -265,6 +275,23 @@ final public function getDecodedContent(): string
return $this->decodedContent;
}

/**
* Get raw message content.
*
* @param string $partNumber
*
* @return string
*/
final protected function doGetContent(string $partNumber): string
{
return \imap_fetchbody(
$this->resource->getStream(),
$this->messageNumber,
$partNumber,
\FT_UID | \FT_PEEK
);
}

/**
* Part structure.
*
Expand Down Expand Up @@ -407,23 +434,6 @@ final public function valid()
return isset($this->parts[$this->key]);
}

/**
* Get raw message content.
*
* @param string $partNumber
*
* @return string
*/
final protected function doGetContent(string $partNumber): string
{
return \imap_fetchbody(
$this->resource->getStream(),
$this->messageNumber,
$partNumber,
\FT_UID | \FT_PEEK
);
}

/**
* Check if the given part is an attachment.
*
Expand Down
17 changes: 16 additions & 1 deletion src/Message/EmbeddedMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,24 @@ public function getRawHeaders(): string
public function getRawMessage(): string
{
if (null === $this->rawMessage) {
$this->rawMessage = \imap_fetchbody($this->resource->getStream(), $this->messageNumber, $this->partNumber, \FT_UID | \FT_PEEK);
$this->rawMessage = $this->doGetContent($this->partNumber);
}

return $this->rawMessage;
}

/**
* Get content part number.
*
* @return string
*/
protected function getContentPartNumber(): string
{
$partNumber = $this->partNumber;
if (0 === \count($this->parts)) {
$partNumber .= '.1';
}

return $partNumber;
}
}
43 changes: 43 additions & 0 deletions tests/EmbeddedMessageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,47 @@ public function testEmbeddedAttachment()

$embeddedAttachment->getEmbeddedMessage();
}

public function testRecursiveEmbeddedAttachment()
{
$mailbox = $this->createMailbox();
$raw = $this->getFixture('four_nested_emails');
$mailbox->addMessage($raw);

$message = $mailbox->getMessage(1);
$this->assertSame('3-third-subject', $message->getSubject());
$this->assertSame('3-third-content', \rtrim($message->getBodyText()));

$attachments = $message->getAttachments();
$this->assertCount(1, $attachments);

$attachment = \current($attachments);
$this->assertTrue($attachment->isEmbeddedMessage());

$embeddedMessage = $attachment->getEmbeddedMessage();
$this->assertSame('2-second-subject', $embeddedMessage->getSubject());
$this->assertSame('2-second-content', \rtrim($embeddedMessage->getBodyText()));

$embeddedAttachments = $embeddedMessage->getAttachments();
$this->assertCount(1, $embeddedAttachments);

$embeddedAttachment = \current($embeddedAttachments);
$this->assertTrue($embeddedAttachment->isEmbeddedMessage());

$secondEmbeddedMessage = $embeddedAttachment->getEmbeddedMessage();
$this->assertSame('1-first-subject', $secondEmbeddedMessage->getSubject());
$this->assertSame('1-first-content', \rtrim($secondEmbeddedMessage->getBodyText()));

$secondEmbeddedAttachments = $secondEmbeddedMessage->getAttachments();
$this->assertCount(1, $secondEmbeddedAttachments);

$secondEmbeddedAttachment = \current($secondEmbeddedAttachments);
$this->assertTrue($secondEmbeddedAttachment->isEmbeddedMessage());

$thirdEmbeddedMessage = $secondEmbeddedAttachment->getEmbeddedMessage();
$this->assertSame('0-zero-subject', $thirdEmbeddedMessage->getSubject());
$this->assertSame('0-zero-content', \rtrim($thirdEmbeddedMessage->getBodyText()));

$this->assertCount(0, $thirdEmbeddedMessage->getAttachments());
}
}
73 changes: 73 additions & 0 deletions tests/fixtures/four_nested_emails.eml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
To: [email protected]
From: [email protected]
Subject: 3-third-subject
Content-Type: multipart/mixed;
boundary="------------2E5D78A17C812FEFF825F7D5"

This is a multi-part message in MIME format.
--------------2E5D78A17C812FEFF825F7D5
Content-Type: text/plain; charset=iso-8859-15; format=flowed
Content-Transfer-Encoding: 7bit
3-third-content
--------------2E5D78A17C812FEFF825F7D5
Content-Type: message/rfc822;
name="2-second-email.eml"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="2-second-email.eml"
To: [email protected]
From: [email protected]
Subject: 2-second-subject
Content-Type: multipart/mixed;
boundary="------------9919377E37A03209B057D47F"
This is a multi-part message in MIME format.
--------------9919377E37A03209B057D47F
Content-Type: text/plain; charset=iso-8859-15; format=flowed
Content-Transfer-Encoding: 7bit
2-second-content
--------------9919377E37A03209B057D47F
Content-Type: message/rfc822;
name="1-first-email.eml"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="1-first-email.eml"
To: [email protected]
From: [email protected]
Subject: 1-first-subject
Content-Type: multipart/mixed;
boundary="------------0919377E37A03209B057D47A"
This is a multi-part message in MIME format.
--------------0919377E37A03209B057D47A
Content-Type: text/plain; charset=iso-8859-15; format=flowed
Content-Transfer-Encoding: 7bit
1-first-content
--------------0919377E37A03209B057D47A
Content-Type: message/rfc822;
name="0-zero-email.eml"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="0-zero-email.eml"
To: [email protected]
From: [email protected]
Subject: 0-zero-subject
Content-Type: text/plain; charset=iso-8859-15; format=flowed
Content-Transfer-Encoding: 7bit
0-zero-content
--------------0919377E37A03209B057D47A--

--------------9919377E37A03209B057D47F--

--------------2E5D78A17C812FEFF825F7D5--

0 comments on commit a5aa591

Please sign in to comment.