Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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']

Expand Down
70 changes: 41 additions & 29 deletions Classes/Finishers/EmailFinisher.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

namespace Neos\Form\Finishers;

/*
Expand All @@ -12,14 +13,19 @@
*/

use Neos\Flow\I18n\Service;
use Neos\Flow\ObjectManagement\ObjectManagerInterface;
use Neos\Flow\ResourceManagement\PersistentResource;
use Neos\FluidAdaptor\View\StandaloneView;
use Neos\Form\Core\Model\AbstractFinisher;
use Neos\Form\Exception\FinisherException;
use Neos\SwiftMailer\Message as SwiftMailerMessage;
use Neos\SymfonyMailer\Service\MailerService;
use Neos\Utility\Arrays;
use Neos\Utility\ObjectAccess;
use Neos\Flow\Annotations as Flow;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\File;

/**
* This finisher sends an email to one or more recipients
Expand Down Expand Up @@ -69,10 +75,8 @@ class EmailFinisher extends AbstractFinisher
*/
protected $i18nService;

protected $formatContentTypes = [
self::FORMAT_HTML => self::CONTENT_TYPE_HTML,
self::FORMAT_PLAINTEXT => self::CONTENT_TYPE_PLAINTEXT,
];
#[Flow\Inject]
protected ObjectManagerInterface $objectManager;

/**
* @var array
Expand All @@ -88,16 +92,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 FinisherException('The "neos/symfonymailer" 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');
Expand All @@ -123,28 +128,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);
Expand All @@ -164,18 +169,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),
};
}
}

Expand Down Expand Up @@ -260,25 +264,25 @@ 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()));
}
}
}
$attachmentConfigurations = $this->parseOption('attachments');
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'])) {
Expand All @@ -288,8 +292,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);
}
}
40 changes: 29 additions & 11 deletions Tests/Functional/AbstractFunctionalTestCase.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

namespace Neos\Form\Tests\Functional;

/*
Expand Down Expand Up @@ -37,17 +38,34 @@ public function setUp(): void
{
parent::setUp();

$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);
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);
}
}

/**
Expand Down
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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": {
Expand Down
Loading