From c70d62a51e73c847096e3f2afcaf2b992ff763e1 Mon Sep 17 00:00:00 2001 From: Karel Vlk Date: Fri, 8 Nov 2024 09:38:57 +0100 Subject: [PATCH] =?UTF-8?q?:bug:=20N=C2=B07916=20SF#2274=20EmailLaminas.ph?= =?UTF-8?q?p:=20Keep=20charset=20with=20part=20header=20in=20multipart=20e?= =?UTF-8?q?mail=20(#672)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * :bug: N°2274 EmailLaminas.php: Keep charset with part header in multipart email * Add a unit test --------- Co-authored-by: Stephen Abello --- sources/Core/Email/EmailLaminas.php | 48 ++----------------- .../unitary-tests/core/EMailTest.php | 39 +++++++++++++++ 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/sources/Core/Email/EmailLaminas.php b/sources/Core/Email/EmailLaminas.php index d00f3be94c..eb0a6d08b4 100644 --- a/sources/Core/Email/EmailLaminas.php +++ b/sources/Core/Email/EmailLaminas.php @@ -7,7 +7,6 @@ */ use Combodo\iTop\Core\Authentication\Client\OAuth\OAuthClientProviderFactory; -use Laminas\Mail\Header\ContentType; use Laminas\Mail\Header\InReplyTo; use Laminas\Mail\Header\MessageId; use Laminas\Mail\Message; @@ -404,19 +403,6 @@ public function SetBody($sBody, $sMimeType = Mime::TYPE_HTML, $sCustomStyles = n $oBody->addPart($oAdditionalPart); } - if ($oBody->isMultiPart()) { - $oContentTypeHeader = $this->m_oMessage->getHeaders(); - foreach ($oContentTypeHeader as $oHeader) { - if (!$oHeader instanceof ContentType) { - continue; - } - - $oHeader->setType(Mime::MULTIPART_MIXED); - $oHeader->addParameter('boundary', $oBody->getMime()->boundary()); - break; - } - } - $this->m_oMessage->setBody($oBody); } @@ -437,22 +423,13 @@ public function AddPart($sText, $sMimeType = Mime::TYPE_HTML) $oNewPart = new Part($sText); $oNewPart->encoding = Mime::ENCODING_8BIT; $oNewPart->type = $sMimeType; - $this->m_oMessage->getBody()->addPart($oNewPart); + + // setBody called only to refresh Content-Type to multipart/mixed + $this->m_oMessage->setBody($this->m_oMessage->getBody()->addPart($oNewPart)); } public function AddAttachment($data, $sFileName, $sMimeType) { - $oBody = $this->m_oMessage->getBody(); - - if (!$oBody->isMultiPart()) { - $multipart_content = new Part($oBody->generateMessage()); - $multipart_content->setType($oBody->getParts()[0]->getType()); - $multipart_content->setBoundary($oBody->getMime()->boundary()); - - $oBody = new Laminas\Mime\Message(); - $oBody->addPart($multipart_content); - } - if (!array_key_exists('attachments', $this->m_aData)) { $this->m_aData['attachments'] = array(); } @@ -463,23 +440,8 @@ public function AddAttachment($data, $sFileName, $sMimeType) $oNewAttachment->disposition = Mime::DISPOSITION_ATTACHMENT; $oNewAttachment->encoding = Mime::ENCODING_BASE64; - - $oBody->addPart($oNewAttachment); - - if ($oBody->isMultiPart()) { - $oContentTypeHeader = $this->m_oMessage->getHeaders(); - foreach ($oContentTypeHeader as $oHeader) { - if (!$oHeader instanceof ContentType) { - continue; - } - - $oHeader->setType(Mime::MULTIPART_MIXED); - $oHeader->addParameter('boundary', $oBody->getMime()->boundary()); - break; - } - } - - $this->m_oMessage->setBody($oBody); + // setBody called only to refresh Content-Type to multipart/mixed + $this->m_oMessage->setBody($this->m_oMessage->getBody()->addPart($oNewAttachment)); } public function SetSubject($sSubject) diff --git a/tests/php-unit-tests/unitary-tests/core/EMailTest.php b/tests/php-unit-tests/unitary-tests/core/EMailTest.php index e0e6f09694..1d9d9c133c 100644 --- a/tests/php-unit-tests/unitary-tests/core/EMailTest.php +++ b/tests/php-unit-tests/unitary-tests/core/EMailTest.php @@ -45,4 +45,43 @@ public function testCheckHeadersOnSendEmail(): void $oConfig->Set('email_transport', $sCurrentEmailTransport); $oConfig->Set('email_asynchronous', $sCurrentEmailAsync); } + + /** + * @return void + * @throws \ConfigException + * @throws \CoreException + * @covers Email::SetBody() + * @covers Email::Send() + */ + public function testCheckPartsHeadersOnSendEmailWithAttachment(): void + { + $oConfig = utils::GetConfig(); + $sCurrentEmailTransport = $oConfig->Get('email_transport'); + $sCurrentEmailAsync = $oConfig->Get('email_asynchronous'); + + // Set our email transport to file, so we can read it after + $oConfig->Set('email_transport', 'LogFile'); + $oConfig->Set('email_asynchronous', false); + + $oEmail = new Email(); + $oEmail->SetRecipientTO('email@email.com'); + $oEmail->SetRecipientFrom('email2@email2.com'); + $oEmail->SetSubject('dummy subject'); + $oEmail->SetBody('dummy body', 'text/plain'); + $oEmail->AddAttachment('Dummy attachment', 'attachment.txt', 'text/plain'); + + // Send the mail and check if there's any issue + $aIssues = []; + $oEmail->Send($aIssues); + $this->assertEmpty($aIssues); + + // Check if our charset is correctly set + // We know this file may be used by other future test, but as we can't configure output filename, it is what it is + $sEmailContent = file_get_contents(APPROOT.'log/mail.log'); + $this->assertStringContainsString('Content-Type: text/plain; charset=UTF-8', $sEmailContent); + + // Set our previous email transport value back, so it doesn't affect other tests + $oConfig->Set('email_transport', $sCurrentEmailTransport); + $oConfig->Set('email_asynchronous', $sCurrentEmailAsync); + } } \ No newline at end of file