Skip to content

Commit 2150ee4

Browse files
committed
[FEATURE] Add Support for Fluid Styled Mails
# Conflicts: # Classes/Domain/Service/SendMailService.php
2 parents f8908e7 + d466e14 commit 2150ee4

File tree

61 files changed

+1419
-264
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1419
-264
lines changed

Classes/Controller/AbstractController.php

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@
2828
use TYPO3\CMS\Core\Http\PropagateResponseException;
2929
use TYPO3\CMS\Core\Http\RedirectResponse;
3030
use TYPO3\CMS\Core\Http\UploadedFile;
31-
use \TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior;
32-
use TYPO3\CMS\Core\Resource\ResourceFactory;
31+
use TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior;
3332
use TYPO3\CMS\Core\Resource\StorageRepository;
3433
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
3534
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
@@ -312,9 +311,9 @@ public function finalCreate(
312311
$this->loginPreflight($user, $login);
313312
$variables = ['user' => $user, 'settings' => $this->settings, 'hash' => HashUtility::createHashForUser($user)];
314313
if (ConfigurationUtility::getValue(
315-
'new./email./createUserNotify./sender./email./value',
316-
$this->config
317-
) && ConfigurationUtility::getValue('new./email./createUserNotify./sender./name./value', $this->config)) {
314+
'new./email./createUserNotify./sender./email./value',
315+
$this->config
316+
) && ConfigurationUtility::getValue('new./email./createUserNotify./sender./name./value', $this->config)) {
318317
$this->sendMailService->send(
319318
'createUserNotify',
320319
StringUtility::makeEmailArray($user->getEmail(), $user->getFirstName() . ' ' . $user->getLastName()),
@@ -608,15 +607,10 @@ public function sendCreateUserConfirmationMail(User $user): void
608607
$this->sendMailService->send(
609608
'createUserConfirmation',
610609
StringUtility::makeEmailArray($user->getEmail(), $user->getUsername()),
611-
[
612-
ConfigurationUtility::getValue(
613-
'new./email./createUserConfirmation./sender./email./value',
614-
$this->config
615-
) => ConfigurationUtility::getValue(
616-
'new./email./createUserConfirmation./sender./name./value',
617-
$this->config
618-
),
619-
],
610+
StringUtility::makeEmailArray(
611+
ConfigurationUtility::getValue('new./email./createUserConfirmation./sender./email./value', $this->config),
612+
ConfigurationUtility::getValue('new./email./createUserConfirmation./sender./name./value', $this->config)
613+
),
620614
$this->contentObject->cObjGetSingle(
621615
(string)ConfigurationUtility::getValue('new./email./createUserConfirmation./subject', $this->config),
622616
(array)ConfigurationUtility::getValue('new./email./createUserConfirmation./subject.', $this->config)
@@ -666,7 +660,8 @@ protected function validateMissingCaptcha(string $redirectAction): void
666660
}
667661
}
668662

669-
protected function isCaptchaEnabled(): bool {
663+
protected function isCaptchaEnabled(): bool
664+
{
670665
$extbaseAttribute = $this->request->getAttribute('extbase');
671666
$controllerName = strtolower($extbaseAttribute->getControllerName());
672667

Classes/Domain/Repository/UserRepository.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ protected function getTreeList($pageIdentifier): array
264264
$pageTreeService = GeneralUtility::makeInstance(PageTreeService::class);
265265
$treeList = $pageTreeService->getTreeList($pageIdentifier, 99, 0, '1');
266266

267-
return GeneralUtility::trimExplode(',', (string) $treeList, true);
267+
return GeneralUtility::trimExplode(',', (string)$treeList, true);
268268
}
269269

270270
protected function ignoreEnableFieldsAndStoragePage(QueryInterface $query)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace In2code\Femanager\Domain\Service\Mail;
6+
7+
use In2code\Femanager\Domain\Service\SendMailService;
8+
use In2code\Femanager\Utility\ObjectUtility;
9+
use Psr\EventDispatcher\EventDispatcherInterface;
10+
use Symfony\Component\Mime\Part\DataPart;
11+
use TYPO3\CMS\Core\Mail\FluidEmail;
12+
use TYPO3\CMS\Core\Mail\MailMessage;
13+
use TYPO3\CMS\Core\Utility\GeneralUtility;
14+
15+
abstract class AbstractMailService implements MailServiceInterface
16+
{
17+
/**
18+
* Content Object
19+
*/
20+
public ?object $contentObject = null;
21+
22+
protected ?EventDispatcherInterface $dispatcher = null;
23+
24+
protected SendMailService $sendMailService;
25+
26+
public function __construct(
27+
SendMailService $sendMailService,
28+
) {
29+
$this->contentObject = ObjectUtility::getContentObject();
30+
$this->dispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class);
31+
$this->sendMailService = $sendMailService;
32+
}
33+
34+
protected function embedImages(array $variables, array $typoScript, FluidEmail|MailMessage $email): array
35+
{
36+
$images = $this->contentObject->cObjGetSingle(
37+
$typoScript['embedImage'] ?? 'TEXT',
38+
$typoScript['embedImage.'] ?? []
39+
);
40+
41+
if (!$images) {
42+
return $variables;
43+
}
44+
45+
$images = GeneralUtility::trimExplode(',', $images, true);
46+
$imageVariables = [];
47+
48+
foreach ($images as $path) {
49+
$name = basename((string)$path);
50+
$imagePart = DataPart::fromPath($path);
51+
$contentType = $imagePart->getMediaType() . '/' . $imagePart->getMediaSubtype();
52+
$email->embedFromPath($path, $name, $contentType);
53+
$imageVariables[] = 'cid:' . $name;
54+
}
55+
56+
return array_merge($variables, ['embedImages' => $imageVariables]);
57+
}
58+
}
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace In2code\Femanager\Domain\Service\Mail;
6+
7+
use In2code\Femanager\Event\AfterMailSendEvent;
8+
use In2code\Femanager\Event\BeforeMailSendEvent;
9+
use In2code\Femanager\Utility\ConfigurationUtility;
10+
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
11+
use Symfony\Component\Mime\Address;
12+
use TYPO3\CMS\Core\Mail\FluidEmail;
13+
use TYPO3\CMS\Core\Mail\MailerInterface;
14+
use TYPO3\CMS\Core\Utility\GeneralUtility;
15+
use TYPO3\CMS\Extbase\Mvc\RequestInterface;
16+
17+
class FluidMailService extends AbstractMailService
18+
{
19+
public function send(
20+
string $template,
21+
array $receiver,
22+
array $sender,
23+
string $subject,
24+
array $variables = [],
25+
array $typoScript = [],
26+
RequestInterface|null $request = null
27+
): bool {
28+
$email = new FluidEmail();
29+
30+
$variables = $this->embedImages($variables, $typoScript, $email);
31+
32+
$typoScriptReceiver = $this->getTypoScriptReceiver($typoScript);
33+
$typoScriptSender = $this->getTypoScriptSender($typoScript);
34+
$attachments = $this->getAttachments($typoScript);
35+
36+
$email
37+
->setRequest($request)
38+
->to(...($typoScriptReceiver ?: $receiver))
39+
->from(...($typoScriptSender ?: $sender))
40+
->subject($this->getTypoScripSubject($typoScript) ?: $subject)
41+
->format(FluidEmail::FORMAT_BOTH)
42+
->setTemplate($template)
43+
->assignMultiple($variables)
44+
->cc(...$this->getCc($typoScript))
45+
->replyTo(...$this->getReplyTo($typoScript))
46+
->priority($this->getPriority($typoScript));
47+
48+
foreach ($attachments as $attachment) {
49+
$email->attachFromPath($attachment);
50+
}
51+
52+
$this->dispatcher->dispatch(new BeforeMailSendEvent($email, $variables, $this->sendMailService));
53+
try {
54+
GeneralUtility::makeInstance(MailerInterface::class)->send($email);
55+
$this->dispatcher->dispatch(new AfterMailSendEvent($email, $variables, $this->sendMailService));
56+
return true;
57+
} catch (TransportExceptionInterface) {
58+
return false;
59+
}
60+
}
61+
62+
public function sendSimple(
63+
string $template,
64+
array $receiver,
65+
array $sender,
66+
string $subject,
67+
array $variables = [],
68+
array $typoScript = [],
69+
RequestInterface|null $request = null
70+
): bool {
71+
$email = new FluidEmail();
72+
$variables = $this->embedImages($variables, $typoScript, $email);
73+
$email
74+
->setRequest($request)
75+
->to(...$receiver)
76+
->from(...$sender)
77+
->subject($subject)
78+
->format(FluidEmail::FORMAT_BOTH)
79+
->setTemplate($template)
80+
->assignMultiple($variables);
81+
82+
$this->dispatcher->dispatch(new BeforeMailSendEvent($email, $variables, $this->sendMailService));
83+
try {
84+
GeneralUtility::makeInstance(MailerInterface::class)->send($email);
85+
$this->dispatcher->dispatch(new AfterMailSendEvent($email, $variables, $this->sendMailService));
86+
return true;
87+
} catch (TransportExceptionInterface) {
88+
return false;
89+
}
90+
}
91+
92+
93+
/**
94+
* @return array<Address>
95+
*/
96+
protected function getTypoScriptReceiver(array $typoScript): array
97+
{
98+
$receiver = [];
99+
$emailAddress = $this->contentObject->cObjGetSingle(
100+
(string)ConfigurationUtility::getValue('receiver./email', $typoScript),
101+
(array)ConfigurationUtility::getValue('receiver./email.', $typoScript)
102+
);
103+
$name = $this->contentObject->cObjGetSingle(
104+
(string)ConfigurationUtility::getValue('receiver./name', $typoScript),
105+
(array)ConfigurationUtility::getValue('receiver./name.', $typoScript)
106+
);
107+
108+
if ($emailAddress && $name) {
109+
$receiver[] = new Address($emailAddress, $name);
110+
}
111+
112+
return $receiver;
113+
}
114+
115+
/**
116+
* @return array<Address>
117+
*/
118+
protected function getTypoScriptSender(array $typoScript): array
119+
{
120+
$sender = [];
121+
$emailAddress = $this->contentObject->cObjGetSingle(
122+
(string)ConfigurationUtility::getValue('sender./email', $typoScript),
123+
(array)ConfigurationUtility::getValue('sender./email.', $typoScript)
124+
);
125+
$name = $this->contentObject->cObjGetSingle(
126+
(string)ConfigurationUtility::getValue('sender./name', $typoScript),
127+
(array)ConfigurationUtility::getValue('sender./name.', $typoScript)
128+
);
129+
130+
if ($emailAddress && $name) {
131+
$sender[] = new Address($emailAddress, $name);
132+
}
133+
134+
return $sender;
135+
}
136+
137+
protected function getTypoScripSubject(array $typoScript): string
138+
{
139+
return $this->contentObject->cObjGetSingle((string)$typoScript['subject'], (array)$typoScript['subject.']);
140+
}
141+
142+
protected function getCc(array $typoScript): array
143+
{
144+
$addresses = [];
145+
foreach (GeneralUtility::trimExplode(
146+
',',
147+
$this->contentObject->cObjGetSingle($typoScript['cc'], $typoScript['cc.']),
148+
true
149+
) as $mail) {
150+
$addresses[] = new Address($mail);
151+
}
152+
153+
return $addresses;
154+
}
155+
156+
protected function getReplyTo(array $typoScript): array
157+
{
158+
$addresses = [];
159+
foreach (GeneralUtility::trimExplode(
160+
',',
161+
$this->contentObject->cObjGetSingle($typoScript['replyTo'], $typoScript['replyTo.']),
162+
true
163+
) as $mail) {
164+
$addresses[] = new Address($mail);
165+
}
166+
167+
return $addresses;
168+
}
169+
170+
protected function getPriority(array $typoScript): int
171+
{
172+
$priority = (int)$this->contentObject->cObjGetSingle(
173+
(string)ConfigurationUtility::getValue('priority', $typoScript),
174+
(array)ConfigurationUtility::getValue('priority.', $typoScript)
175+
);
176+
if ($priority !== 0) {
177+
return $priority;
178+
}
179+
180+
// default priority
181+
return 1;
182+
}
183+
184+
protected function getAttachments(array $typoScript): array
185+
{
186+
$attachments = [];
187+
if ($this->contentObject->cObjGetSingle($typoScript['attachments'] ?? '', $typoScript['attachments.'] ?? [])) {
188+
$files = GeneralUtility::trimExplode(
189+
',',
190+
$this->contentObject->cObjGetSingle(
191+
$typoScript['attachments'] ?? '',
192+
$typoScript['attachments.'] ?? []
193+
),
194+
true
195+
);
196+
foreach ($files as $file) {
197+
$attachments[] = $file;
198+
}
199+
}
200+
201+
return $attachments;
202+
}
203+
204+
}

0 commit comments

Comments
 (0)