From 330118c5667da48615a92a7b956ffe413a86b913 Mon Sep 17 00:00:00 2001 From: Denny Lubitz Date: Tue, 15 Apr 2025 10:38:52 +0200 Subject: [PATCH 1/3] FEATURE: Replace swiftmailer with symfonymailer --- .github/workflows/tests.yml | 2 +- Classes/Finishers/EmailFinisher.php | 71 +++++++++++-------- .../Functional/AbstractFunctionalTestCase.php | 40 ++++++++--- composer.json | 6 +- 4 files changed, 75 insertions(+), 44 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 61d72d4..4168e10 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - php-versions: ['8.1', '8.3'] + php-versions: ['8.2', '8.3'] flow-versions: ['8.0', '8.3', '9.0'] dependencies: ['highest'] diff --git a/Classes/Finishers/EmailFinisher.php b/Classes/Finishers/EmailFinisher.php index 05f5e18..28335e1 100644 --- a/Classes/Finishers/EmailFinisher.php +++ b/Classes/Finishers/EmailFinisher.php @@ -1,4 +1,5 @@ self::CONTENT_TYPE_HTML, - self::FORMAT_PLAINTEXT => self::CONTENT_TYPE_PLAINTEXT, - ]; + #[Flow\Inject] + protected ObjectManagerInterface $objectManager; /** * @var array @@ -88,16 +93,17 @@ class EmailFinisher extends AbstractFinisher /** * Executes this finisher - * @see AbstractFinisher::execute() - * * @return void * @throws FinisherException + * @see AbstractFinisher::execute() + * */ protected function executeInternal() { - if (!class_exists(SwiftMailerMessage::class)) { - throw new FinisherException('The "neos/swiftmailer" doesn\'t seem to be installed, but is required for the EmailFinisher to work!', 1503392532); + if (!class_exists(MailerService::class)) { + throw new ActionException('The "neos/swiftmailer" doesn\'t seem to be installed, but is required for the EmailFinisher to work!', 1503392532); } + $subject = $this->parseOption('subject'); $recipientAddress = $this->parseOption('recipientAddress'); $recipientName = $this->parseOption('recipientName'); @@ -123,28 +129,28 @@ protected function executeInternal() throw new FinisherException('The option "senderAddress" must be set for the EmailFinisher.', 1327060210); } - $mail = new SwiftMailerMessage(); + $mail = new Email(); $mail - ->setFrom(array($senderAddress => $senderName)) - ->setSubject($subject); + ->addFrom(new Address($senderAddress, $senderName)) + ->subject($subject); if (is_array($recipientAddress)) { - $mail->setTo($recipientAddress); + $mail->addTo(...array_map(fn ($entry) => new Address($entry), $recipientAddress)); } else { - $mail->setTo(array($recipientAddress => $recipientName)); + $mail->addTo(new Address($recipientAddress, $recipientName)); } if ($replyToAddress !== null) { - $mail->setReplyTo($replyToAddress); + $mail->addReplyTo(new Address($replyToAddress)); } if ($carbonCopyAddress !== null) { - $mail->setCc($carbonCopyAddress); + $mail->addCc(new Address($carbonCopyAddress)); } if ($blindCarbonCopyAddress !== null) { - $mail->setBcc($blindCarbonCopyAddress); + $mail->addBcc(new Address($blindCarbonCopyAddress)); } $this->addMessages($mail, $messages); @@ -164,18 +170,17 @@ protected function executeInternal() 'E-Mail "' . $subject . '"' ); } else { - $mail->send(); + $this->getMailerService()->getMailer()->send($mail); } } - protected function addMessages(SwiftMailerMessage $mail, array $messages): void + protected function addMessages(Email $mail, array $messages): void { foreach ($messages as $messageFormat => $message) { - if (count($messages) === 1) { - $mail->setBody($message, $this->formatContentTypes[$messageFormat]); - } else { - $mail->addPart($message, $this->formatContentTypes[$messageFormat]); - } + match ($messageFormat) { + self::FORMAT_HTML => $mail->html($message), + self::FORMAT_PLAINTEXT => $mail->text($message), + }; } } @@ -260,17 +265,17 @@ protected function initializeStandaloneView(string $format = ''): StandaloneView } /** - * @param SwiftMailerMessage $mail + * @param Email $mail * @return void * @throws FinisherException */ - protected function addAttachments(SwiftMailerMessage $mail) + protected function addAttachments(Email $mail) { $formValues = $this->finisherContext->getFormValues(); if ($this->parseOption('attachAllPersistentResources')) { foreach ($formValues as $formValue) { if ($formValue instanceof PersistentResource) { - $mail->attach(new \Swift_Attachment(stream_get_contents($formValue->getStream()), $formValue->getFilename(), $formValue->getMediaType())); + $mail->addPart(new DataPart($formValue->getStream(), $formValue->getFilename(), $formValue->getMediaType())); } } } @@ -278,7 +283,7 @@ protected function addAttachments(SwiftMailerMessage $mail) if (is_array($attachmentConfigurations)) { foreach ($attachmentConfigurations as $attachmentConfiguration) { if (isset($attachmentConfiguration['resource'])) { - $mail->attach(\Swift_Attachment::fromPath($attachmentConfiguration['resource'])); + $mail->addPart(new DataPart(new File($attachmentConfiguration['resource']))); continue; } if (!isset($attachmentConfiguration['formElement'])) { @@ -288,8 +293,16 @@ protected function addAttachments(SwiftMailerMessage $mail) if (!$resource instanceof PersistentResource) { continue; } - $mail->attach(new \Swift_Attachment(stream_get_contents($resource->getStream()), $resource->getFilename(), $resource->getMediaType())); + $content = stream_get_contents($resource->getStream()); + if (!is_bool($content)) { + $mail->addPart(new DataPart($content, $resource->getFilename(), $resource->getMediaType())); + } } } } + + private function getMailerService(): MailerService + { + return $this->objectManager->get(MailerService::class); + } } diff --git a/Tests/Functional/AbstractFunctionalTestCase.php b/Tests/Functional/AbstractFunctionalTestCase.php index a0b1976..c254f75 100644 --- a/Tests/Functional/AbstractFunctionalTestCase.php +++ b/Tests/Functional/AbstractFunctionalTestCase.php @@ -1,4 +1,5 @@ setUriPattern('test/form/simpleform/{formFactoryClassName}'); - $route->setDefaults([ - '@package' => 'Neos.Form', - '@subpackage' => 'Tests\Functional\Fixtures', - '@controller' => 'Form', - '@action' => 'index', - '@format' => 'html' - ]); - $route->setAppendExceedingArguments(true); - $this->router->addRoute($route); + if (method_exists($this, 'registerRoute')) { + // Flow 9.x + $this->registerRoute( + 'Functional Test - Neos.Form', + 'test/form/simpleform/{formFactoryClassName}', + [ + '@package' => 'Neos.Form', + '@subpackage' => 'Tests\Functional\Fixtures', + '@controller' => 'Form', + '@action' => 'index', + '@format' => 'html' + ], + true + ); + } else { + // Flow 8.x + $route = new Route(); + $route->setUriPattern('test/form/simpleform/{formFactoryClassName}'); + $route->setDefaults([ + '@package' => 'Neos.Form', + '@subpackage' => 'Tests\Functional\Fixtures', + '@controller' => 'Form', + '@action' => 'index', + '@format' => 'html' + ]); + $route->setAppendExceedingArguments(true); + $this->router->addRoute($route); + } } /** diff --git a/composer.json b/composer.json index 7af931f..5677136 100755 --- a/composer.json +++ b/composer.json @@ -4,8 +4,8 @@ "license": "MIT", "description": "Extensible and flexible API for building web forms", "require": { - "php": "^8.0", - "neos/flow": "^7.3 || ^8.0 || ^9.0" + "php": "^8.2", + "neos/flow": "^8.0 || ^9.0" }, "replace": { "typo3/form": "self.version" @@ -21,7 +21,7 @@ } }, "suggest": { - "neos/swiftmailer": "The EmailFinisher needs this to be useable" + "neos/symfonymailer": "The EmailFinisher needs this to be useable" }, "extra": { "branch-alias": { From 6ed3fd858a7e5e0922004a1d9fde5f7994f938d5 Mon Sep 17 00:00:00 2001 From: Denny Lubitz Date: Tue, 15 Apr 2025 10:41:42 +0200 Subject: [PATCH 2/3] FEATURE: Replace swiftmailer with symfonymailer --- Classes/Finishers/EmailFinisher.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/Finishers/EmailFinisher.php b/Classes/Finishers/EmailFinisher.php index 28335e1..d229687 100644 --- a/Classes/Finishers/EmailFinisher.php +++ b/Classes/Finishers/EmailFinisher.php @@ -101,7 +101,7 @@ class EmailFinisher extends AbstractFinisher protected function executeInternal() { if (!class_exists(MailerService::class)) { - throw new ActionException('The "neos/swiftmailer" doesn\'t seem to be installed, but is required for the EmailFinisher to work!', 1503392532); + throw new ActionException('The "neos/symfonymailer" doesn\'t seem to be installed, but is required for the EmailFinisher to work!', 1503392532); } $subject = $this->parseOption('subject'); From 01f1ba3f554f36bdc8e89b862740b8c771585b0e Mon Sep 17 00:00:00 2001 From: Denny Lubitz Date: Tue, 15 Apr 2025 12:31:53 +0200 Subject: [PATCH 3/3] FEATURE: Replace swiftmailer with symfonymailer --- Classes/Finishers/EmailFinisher.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Classes/Finishers/EmailFinisher.php b/Classes/Finishers/EmailFinisher.php index d229687..9421c78 100644 --- a/Classes/Finishers/EmailFinisher.php +++ b/Classes/Finishers/EmailFinisher.php @@ -18,7 +18,6 @@ use Neos\FluidAdaptor\View\StandaloneView; use Neos\Form\Core\Model\AbstractFinisher; use Neos\Form\Exception\FinisherException; -use Neos\Fusion\Form\Runtime\Domain\Exception\ActionException; use Neos\SymfonyMailer\Service\MailerService; use Neos\Utility\Arrays; use Neos\Utility\ObjectAccess; @@ -101,7 +100,7 @@ class EmailFinisher extends AbstractFinisher protected function executeInternal() { if (!class_exists(MailerService::class)) { - throw new ActionException('The "neos/symfonymailer" doesn\'t seem to be installed, but is required for the EmailFinisher to work!', 1503392532); + throw new FinisherException('The "neos/symfonymailer" doesn\'t seem to be installed, but is required for the EmailFinisher to work!', 1503392532); } $subject = $this->parseOption('subject');