-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix parsing of attachment's filename in MailgunMailer
Filename is parsed from header `Content-Disposition`. It is put there by Nette Mailer. Previous implementation incorrectly parsed filenames with dash. Filename of attached file "invoice-2024-09-24.pdf" would be only last part "24.pdf". Regex responsible for parsing header was moved into trait MailHeaderTrait so it can be tested. remp/remp#1386 Co-authored-by: Peter Dulacka <dulacka@gmail.com>
- Loading branch information
Showing
4 changed files
with
103 additions
and
2 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
22 changes: 22 additions & 0 deletions
22
Mailer/extensions/mailer-module/src/Models/Mailer/MailHeaderTrait.php
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,22 @@ | ||
<?php | ||
|
||
namespace Remp\MailerModule\Models\Mailer; | ||
|
||
trait MailHeaderTrait | ||
{ | ||
/** | ||
* Get parameter from header string | ||
* | ||
* <code> | ||
* $headerValue = 'Content-Disposition: attachment; filename="invoice-2024-09-24.pdf"'; | ||
* // $filename will contain string "invoice-2024-09-24.pdf" | ||
* $filename = $this->getHeaderParameter($headerValue, 'filename'); | ||
* </code> | ||
*/ | ||
public function getHeaderParameter(string $headerValue, string $parameter): ?string | ||
{ | ||
preg_match('/.*' . $parameter . '="(?<value>([^"]*))"/', $headerValue, $result); | ||
return $result['value'] ?? null; | ||
} | ||
} |
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
73 changes: 73 additions & 0 deletions
73
Mailer/extensions/mailer-module/src/Tests/Feature/Mails/MailHeaderTraitTest.php
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,73 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
namespace Feature\Mails; | ||
|
||
use Nette\Mail\Message; | ||
use PHPUnit\Framework\Attributes\DataProvider; | ||
use Remp\MailerModule\Models\Mailer\MailHeaderTrait; | ||
use Tests\Feature\BaseFeatureTestCase; | ||
|
||
class MailHeaderTraitTest extends BaseFeatureTestCase | ||
{ | ||
use MailHeaderTrait; | ||
|
||
public static function dataProvider() | ||
{ | ||
return [ | ||
'TestRegularHeader_ShouldReturnFilename' => [ | ||
'headerValue' => 'Content-Disposition: attachment; filename="invoice-2024-09-24.pdf"', | ||
'parameter' => 'filename', | ||
'result' => 'invoice-2024-09-24.pdf', | ||
], | ||
'TestRegularHeader_NotRealParameter' => [ | ||
'headerValue' => 'Content-Disposition: attachment; filename="invoice-2024-09-24.pdf"', | ||
'parameter' => 'dummy', | ||
'result' => null, | ||
], | ||
'TestRegularHeader_AdditionalParameters' => [ | ||
'headerValue' => 'Content-Disposition: attachment; filename="invoice-2024-09-24.pdf"; foo="bar"', | ||
'parameter' => 'filename', | ||
'result' => 'invoice-2024-09-24.pdf', | ||
], | ||
]; | ||
} | ||
|
||
#[DataProvider('dataProvider')] | ||
public function testMailHeaderTrait( | ||
string $headerValue, | ||
string $parameter, | ||
?string $result, | ||
) { | ||
$parameter = $this->getHeaderParameter($headerValue, $parameter); | ||
$this->assertSame($result, $parameter); | ||
} | ||
|
||
/** | ||
* Nette Mailer adds attachments to email as `Content-Disposition` headers with format: | ||
* | ||
* Content-Disposition: attachment; filename="invoice-2024-09-24.pdf" | ||
* | ||
* Mailgun requires attachments as API parameters, so in MailgunMailer we need to load attachment | ||
* and parse filename from header. This is handled by preg_match within `MailHeaderTrait`. | ||
* | ||
* This is simple unit test which checks: | ||
* - If regex which loads attachment's filename from mail header is correct. | ||
* - If Nette didn't change how attachments (filenames) are attached to message. | ||
* E.g. using different approach or attaching filename without quotes (allowed by specification). | ||
*/ | ||
public function testMessageMimePartHeaderForContentDisposition() | ||
{ | ||
$filename = 'invoice-2024-09-24.pdf'; | ||
|
||
// create attachment as Nette Mailer creates it | ||
$message = new Message(); | ||
$message->addAttachment($filename, 'dummy content', 'text/plain'); | ||
$attachments = $message->getAttachments(); | ||
$attachment = reset($attachments); | ||
|
||
// parse header created by Nette with our Trait | ||
$attachmentName = $this->getHeaderParameter($attachment->getHeader('Content-Disposition'), 'filename'); | ||
$this->assertEquals($filename, $attachmentName); | ||
} | ||
} |