Skip to content

Commit

Permalink
Lazy load headers
Browse files Browse the repository at this point in the history
  • Loading branch information
Slamdunk committed Oct 19, 2017
1 parent 1e298f3 commit 850f0c8
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 49 deletions.
68 changes: 58 additions & 10 deletions src/Message/AbstractMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Ddeboer\Imap\Message;

use Ddeboer\Imap\Exception\InvalidDateHeaderException;

abstract class AbstractMessage extends AbstractPart
{
/**
Expand All @@ -30,7 +32,9 @@ final public function getId(): string
*/
final public function getFrom()
{
return $this->getHeaders()->get('from');
$from = $this->getHeaders()->get('from');

return null !== $from ? $this->decodeEmailAddress($from[0]) : null;
}

/**
Expand All @@ -40,7 +44,7 @@ final public function getFrom()
*/
final public function getTo(): array
{
return $this->getHeaders()->get('to') ?: [];
return $this->decodeEmailAddresses($this->getHeaders()->get('to') ?: []);
}

/**
Expand All @@ -50,7 +54,7 @@ final public function getTo(): array
*/
final public function getCc(): array
{
return $this->getHeaders()->get('cc') ?: [];
return $this->decodeEmailAddresses($this->getHeaders()->get('cc') ?: []);
}

/**
Expand All @@ -60,7 +64,7 @@ final public function getCc(): array
*/
final public function getBcc(): array
{
return $this->getHeaders()->get('bcc') ?: [];
return $this->decodeEmailAddresses($this->getHeaders()->get('bcc') ?: []);
}

/**
Expand All @@ -70,7 +74,7 @@ final public function getBcc(): array
*/
final public function getReplyTo(): array
{
return $this->getHeaders()->get('reply_to') ?: [];
return $this->decodeEmailAddresses($this->getHeaders()->get('reply_to') ?: []);
}

/**
Expand All @@ -80,7 +84,7 @@ final public function getReplyTo(): array
*/
final public function getSender(): array
{
return $this->getHeaders()->get('sender') ?: [];
return $this->decodeEmailAddresses($this->getHeaders()->get('sender') ?: []);
}

/**
Expand All @@ -90,7 +94,7 @@ final public function getSender(): array
*/
final public function getReturnPath(): array
{
return $this->getHeaders()->get('return_path') ?: [];
return $this->decodeEmailAddresses($this->getHeaders()->get('return_path') ?: []);
}

/**
Expand All @@ -100,7 +104,24 @@ final public function getReturnPath(): array
*/
final public function getDate()
{
return $this->getHeaders()->get('date');
$dateHeader = $this->getHeaders()->get('date');
if (null === $dateHeader) {
return;
}

$alteredValue = \str_replace(',', '', $dateHeader);
$alteredValue = \preg_replace('/ +\(.*\)/', '', $alteredValue);
if (0 === \preg_match('/\d\d:\d\d:\d\d.* [\+\-]?\d\d:?\d\d/', $alteredValue)) {
$alteredValue .= ' +0000';
}

try {
$date = new \DateTimeImmutable($alteredValue);
} catch (\Throwable $ex) {
throw new InvalidDateHeaderException(\sprintf('Invalid Date header found: "%s"', $dateHeader), 0, $ex);
}

return $date;
}

/**
Expand Down Expand Up @@ -132,7 +153,7 @@ final public function getInReplyTo(): array
{
$inReplyTo = $this->getHeaders()->get('in_reply_to');

return \is_array($inReplyTo) ? $inReplyTo : [];
return null !== $inReplyTo ? \explode(' ', $inReplyTo) : [];
}

/**
Expand All @@ -144,7 +165,7 @@ final public function getReferences(): array
{
$references = $this->getHeaders()->get('references');

return \is_array($references) ? $references : [];
return null !== $references ? \explode(' ', $references) : [];
}

/**
Expand Down Expand Up @@ -226,4 +247,31 @@ final public function hasAttachments(): bool
{
return \count($this->getAttachments()) > 0;
}

/**
* @param array $addresses Addesses
*
* @return array
*/
private function decodeEmailAddresses(array $addresses): array
{
$return = [];
foreach ($addresses as $address) {
if (isset($address->mailbox)) {
$return[] = $this->decodeEmailAddress($address);
}
}

return $return;
}

/**
* @param \stdClass $value
*
* @return EmailAddress
*/
private function decodeEmailAddress(\stdClass $value): EmailAddress
{
return new EmailAddress($value->mailbox, $value->host, $value->personal);
}
}
42 changes: 4 additions & 38 deletions src/Message/Headers.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

namespace Ddeboer\Imap\Message;

use Ddeboer\Imap\Exception\InvalidDateHeaderException;

/**
* Collection of message headers.
*/
Expand Down Expand Up @@ -51,58 +49,26 @@ private function parseHeader(string $key, $value)
switch ($key) {
case 'msgno':
return (int) $value;
case 'date':
$value = $this->decode($value);
$alteredValue = \str_replace(',', '', $value);
$alteredValue = \preg_replace('/ +\(.*\)/', '', $alteredValue);
if (0 === \preg_match('/\d\d:\d\d:\d\d.* [\+\-]?\d\d:?\d\d/', $alteredValue)) {
$alteredValue .= ' +0000';
}

try {
$date = new \DateTimeImmutable($alteredValue);
} catch (\Throwable $ex) {
throw new InvalidDateHeaderException(\sprintf('Invalid Date header found: "%s"', $value), 0, $ex);
}

return $date;
case 'from':
return $this->decodeEmailAddress(\current($value));
case 'to':
case 'cc':
case 'bcc':
case 'reply_to':
case 'sender':
case 'return_path':
$emails = [];
foreach ($value as $address) {
if (isset($address->mailbox)) {
$emails[] = $this->decodeEmailAddress($address);
$address->host = $address->host ?? null;
$address->personal = isset($address->personal) ? $this->decode($address->personal) : null;
}
}

return $emails;
return $value;
case 'date':
case 'subject':
return $this->decode($value);
case 'in_reply_to':
case 'references':
return \explode(' ', $value);
}

return $value;
}

/**
* @param \stdClass $value
*
* @return EmailAddress
*/
private function decodeEmailAddress(\stdClass $value): EmailAddress
{
return new EmailAddress(
$value->mailbox,
isset($value->host) ? $value->host : null,
isset($value->personal) ? $this->decode($value->personal) : null
);
}
}
3 changes: 3 additions & 0 deletions tests/MessageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,9 @@ public function testGetAllHeaders()
$this->assertArrayHasKey('date', $headers);
$this->assertArrayHasKey('recent', $headers);

$this->assertSame('Wed, 27 Sep 2017 12:48:51 +0200', $headers['date']);
$this->assertSame('A_€@{è_Z', $headers['bcc'][0]->personal);

$this->assertFalse($message->isSeen());
}

Expand Down
2 changes: 1 addition & 1 deletion tests/fixtures/bcc.eml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Content-Type: text/plain
Date: Wed, 27 Sep 2017 12:48:51 +0200
From: [email protected]
To: [email protected]
Bcc: [email protected]
Bcc: =?UTF-8?B?QV/igqxAe8OoX1o=?= <[email protected]>
Reply-To: [email protected]
Sender: [email protected]

Expand Down

0 comments on commit 850f0c8

Please sign in to comment.