-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #45 from fcoedno/mime-decode
Decode mime headers
- Loading branch information
Showing
6 changed files
with
276 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace rpkamp\Mailhog\Message; | ||
|
||
use function iconv_mime_decode; | ||
use function strtolower; | ||
|
||
class Headers | ||
{ | ||
/** | ||
* @var array<string, string> $headers | ||
*/ | ||
private $headers; | ||
|
||
/** | ||
* @param array<string, string> $headers | ||
*/ | ||
public function __construct(array $headers) | ||
{ | ||
$this->headers = $headers; | ||
} | ||
|
||
/** | ||
* @param array<mixed, mixed> $mailhogResponse | ||
*/ | ||
public static function fromMailhogResponse(array $mailhogResponse): self | ||
{ | ||
return self::fromRawHeaders($mailhogResponse['Content']['Headers'] ?? []); | ||
} | ||
|
||
/** | ||
* @param array<mixed, mixed> $mimePart | ||
*/ | ||
public static function fromMimePart(array $mimePart): self | ||
{ | ||
return self::fromRawHeaders($mimePart['Headers']); | ||
} | ||
|
||
/** | ||
* @param array<string, array<string>> $rawHeaders | ||
*/ | ||
private static function fromRawHeaders(array $rawHeaders): self | ||
{ | ||
$headers = []; | ||
foreach ($rawHeaders as $name => $header) { | ||
if (!isset($header[0])) { | ||
continue; | ||
} | ||
|
||
$decoded = iconv_mime_decode($header[0]); | ||
|
||
$headers[strtolower($name)] = $decoded ? $decoded : $header[0]; | ||
} | ||
|
||
return new Headers($headers); | ||
} | ||
|
||
public function get(string $name, string $default = ''): string | ||
{ | ||
$name = strtolower($name); | ||
|
||
if (isset($this->headers[$name])) { | ||
return $this->headers[$name]; | ||
} | ||
|
||
return $default; | ||
} | ||
|
||
public function has(string $name): bool | ||
{ | ||
$name = strtolower($name); | ||
|
||
return isset($this->headers[$name]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
{ | ||
"total":1, | ||
"count":1, | ||
"start":0, | ||
"items":[ | ||
{ | ||
"ID":"1SepfeC9XRP7xKMDmPfczx8k3ktwjh605ZVatm4L9ew=@mailhog.example", | ||
"From":{ | ||
"Relays":null, | ||
"Mailbox":"no-reply", | ||
"Domain":"myself.example", | ||
"Params":"" | ||
}, | ||
"To":[ | ||
{ | ||
"Relays":null, | ||
"Mailbox":"jose", | ||
"Domain":"myself.example", | ||
"Params":"" | ||
}, | ||
{ | ||
"Relays":null, | ||
"Mailbox":"leticia", | ||
"Domain":"myself.example", | ||
"Params":"" | ||
} | ||
], | ||
"Content":{ | ||
"Headers":{ | ||
"Content-Transfer-Encoding":[ | ||
"quoted-printable" | ||
], | ||
"Content-Type":[ | ||
"text/html; charset=utf-8" | ||
], | ||
"Date":[ | ||
"Sun, 06 Sep 2020 15:24:56 -0300" | ||
], | ||
"From":[ | ||
"=?utf-8?Q?Jos=C3=A9?= de tal \u003cno-reply@myself.example\u003e" | ||
], | ||
"MIME-Version":[ | ||
"1.0" | ||
], | ||
"Message-ID":[ | ||
"\u003c3f91997768d3c98ab3e19cebb5a731f8@swift.generated\u003e" | ||
], | ||
"Received":[ | ||
"from [127.0.0.1] by mailhog.example (MailHog)\r\n id 1SepfeC9XRP7xKMDmPfczx8k3ktwjh605ZVatm4L9ew=@mailhog.example; Sun, 06 Sep 2020 18:24:56 +0000" | ||
], | ||
"Return-Path":[ | ||
"\u003cno-reply@myself.example\u003e" | ||
], | ||
"Subject":[ | ||
"Mailhog =?utf-8?Q?=C3=A9?= muito bom mesmo: =?utf-8?Q?=F0=9F=98=81?=" | ||
], | ||
"To":[ | ||
"=?utf-8?Q?Jos=C3=A9?= \u003cjose@myself.example\u003e, =?utf-8?Q?Let=C3=ADcia_maranh=C3=A3o?= \u003cleticia@myself.example\u003e" | ||
] | ||
}, | ||
"Body":"foobar", | ||
"Size":474, | ||
"MIME":null | ||
}, | ||
"Created":"2020-09-06T18:24:56.58754722Z", | ||
"MIME":null, | ||
"Raw":{ | ||
"From":"no-reply@myself.example", | ||
"To":[ | ||
"jose@myself.example", | ||
"leticia@myself.example" | ||
], | ||
"Data":"Message-ID: \u003c3f91997768d3c98ab3e19cebb5a731f8@swift.generated\u003e\r\nDate: Sun, 06 Sep 2020 15:24:56 -0300\r\nSubject: Mailhog =?utf-8?Q?=C3=A9?= muito bom mesmo:\r\n =?utf-8?Q?=F0=9F=98=81?=\r\nFrom: =?utf-8?Q?Jos=C3=A9?= de tal \u003cno-reply@myself.example\u003e\r\nTo: =?utf-8?Q?Jos=C3=A9?= \u003cjose@myself.example\u003e,\r\n =?utf-8?Q?Let=C3=ADcia_maranh=C3=A3o?= \u003cleticia@myself.example\u003e\r\nMIME-Version: 1.0\r\nContent-Type: text/html; charset=utf-8\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\nfoobar", | ||
"Helo":"[127.0.0.1]" | ||
} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace rpkamp\Mailhog\Tests\unit\Message; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
use rpkamp\Mailhog\Message\Headers; | ||
|
||
class HeadersTest extends TestCase | ||
{ | ||
/** | ||
* @test | ||
*/ | ||
public function it_should_parse_headers(): void | ||
{ | ||
$messageData = $this->getMessageData(); | ||
$headers = Headers::fromMailHogResponse($messageData); | ||
|
||
$this->assertEquals( | ||
"Mailhog é muito bom mesmo: 😁", | ||
$headers->get("Subject") | ||
); | ||
|
||
$this->assertEquals( | ||
"José <jose@myself.example>, Letícia maranhão <leticia@myself.example>", | ||
$headers->get("To") | ||
); | ||
|
||
$this->assertEquals( | ||
"José de tal <no-reply@myself.example>", | ||
$headers->get("From") | ||
); | ||
|
||
$this->assertEquals( | ||
"quoted-printable", | ||
$headers->get("Content-Transfer-Encoding") | ||
); | ||
|
||
$this->assertEquals( | ||
"text/html; charset=utf-8", | ||
$headers->get("Content-Type") | ||
); | ||
} | ||
|
||
/** | ||
* @test | ||
*/ | ||
public function it_should_ignore_case_for_the_header_name(): void | ||
{ | ||
$messageData = $this->getMessageData(); | ||
$headers = Headers::fromMailHogResponse($messageData); | ||
|
||
$this->assertEquals( | ||
"José de tal <no-reply@myself.example>", | ||
$headers->get("from") | ||
); | ||
} | ||
|
||
/** | ||
* @test | ||
*/ | ||
public function it_should_return_the_default_value_when_the_header_does_not_exist(): void | ||
{ | ||
$headers = new Headers([]); | ||
|
||
$this->assertEquals( | ||
'default value', | ||
$headers->get('foobar', 'default value') | ||
); | ||
} | ||
|
||
/** | ||
* @test | ||
*/ | ||
public function it_should_check_if_a_header_exists(): void | ||
{ | ||
$headers = new Headers([]); | ||
$this->assertFalse($headers->has('foobar')); | ||
} | ||
|
||
/** | ||
* @return array<mixed, mixed> | ||
*/ | ||
private function getMessageData(): array | ||
{ | ||
$contents = file_get_contents(__DIR__ . '/Fixtures/sample_mailhog_response.json'); | ||
if (!$contents) { | ||
return []; | ||
} | ||
|
||
$allMessagesData = json_decode($contents, true); | ||
return $allMessagesData['items'][0]; | ||
} | ||
} |