Newer
Older
<?php
namespace SGalinski\SgMail\Service;

Torsten Oppermann
committed
/***************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (https://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/

Torsten Oppermann
committed
use DateTime;
use SGalinski\SgMail\Domain\Model\Mail;
use SGalinski\SgMail\Domain\Model\Template;
use SGalinski\SgMail\Domain\Repository\LayoutRepository;
use SGalinski\SgMail\Domain\Repository\MailRepository;
use SGalinski\SgMail\Domain\Repository\TemplateRepository;
use Swift_Attachment;
use Swift_OutputByteStream;

Torsten Oppermann
committed
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Mail\MailMessage;
Fabian Galinski
committed
use TYPO3\CMS\Core\Resource\File;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Domain\Model\FileReference;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
/**
* MailTemplateService
*/
class MailTemplateService {
const MARKER_TYPE_STRING = 'String';
const MARKER_TYPE_ARRAY = 'Array';
const MARKER_TYPE_OBJECT = 'Object';
const MARKER_TYPE_FILE = 'File';
const DEFAULT_LANGUAGE = 'default';
const DEFAULT_TEMPLATE_PATH = 'Resources/Private/Templates/SgMail/';
const CACHE_NAME = 'sg_mail_registerArrayCache';
const CACHE_LIFETIME_IN_SECONDS = 86400;
const REGISTER_FILE = 'Register.php';
const CONFIG_PATH = 'Configuration/MailTemplates';
Stefan Galinski
committed
* @var string $toAddresses
Stefan Galinski
committed
private $toAddresses = '';
Stefan Galinski
committed
private $fromAddress = '';
Stefan Galinski
committed
* @var string $ccAddresses
Stefan Galinski
committed
private $replyToAddress = '';
private $language = 'default';
* @var boolean $ignoreMailQueue
/**
* @var \TYPO3\CMS\Core\Mail\MailMessage $mailMessage
*/
private $mailMessage;
/**
*/
private $templateName;
/**
* @var string $subject
*/
private $subject;
/**
* @var string $overwrittenEmailBody
*/
private $overwrittenEmailBody = '';
*/
private $extensionKey;
/**
/**
* @var array $markerLabels
*/
private $markerLabels;
Stefan Galinski
committed
* @var string $bccAddresses
/**
* @var int
*/
private $priority = Mail::PRIORITY_LOWEST;
/**
* @var int
*/
private $pid;
/**
* @var string
*/
private $fromName = '';

Torsten Oppermann
committed
/**
* @var \SGalinski\SgMail\Domain\Repository\TemplateRepository
*/
protected $templateRepository;
/**
* @var \SGalinski\SgMail\Domain\Repository\LayoutRepository
*/
protected $layoutRepository;
/**
* @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
*/
protected $persistenceManager;

Torsten Oppermann
committed

Markus Guenther
committed
/**
* @var \TYPO3\CMS\Extbase\Object\ObjectManager
*/
protected $objectManager;
/**
* @var TYPO3\CMS\Core\Resource\ResourceFactory
*/
protected $resourceFactory;
/**
* MailTemplateService constructor.
* @param string $templateName
* @param string $extensionKey
* @param array $markers
* @param array $markerLabels
public function __construct($templateName = '', $extensionKey = '', $markers = [], $markerLabels = []) {
$this->templateName = $templateName;
$this->extensionKey = $extensionKey;
$this->markers = $markers;
$this->markerLabels = $markerLabels;

Markus Guenther
committed
/** @var ObjectManager objectManager */
$this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$this->mailMessage = $this->objectManager->get(MailMessage::class);
$typoScriptSettingsService = $this->objectManager->get(TypoScriptSettingsService::class);
$tsSettings = $typoScriptSettingsService->getSettings(0, 'tx_sgmail');

Markus Guenther
committed
$this->templateRepository = $this->objectManager->get(TemplateRepository::class);
$this->layoutRepository = $this->objectManager->get(LayoutRepository::class);

Markus Guenther
committed
$this->persistenceManager = $this->objectManager->get(PersistenceManager::class);
$this->resourceFactory = $this->objectManager->get(ResourceFactory::class);
// use defaultMailFromAddress if it is provided in LocalConfiguration.php; use the sg_mail TS setting as fallback
if (\filter_var($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'], FILTER_VALIDATE_EMAIL)) {
$this->fromAddress = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'];
} else {
$this->fromAddress = $tsSettings['mail']['default']['from'];
if (!\filter_var($tsSettings['mail']['default']['from'], FILTER_VALIDATE_EMAIL)) {
$this->fromAddress = 'noreply@example.org';
} else {
$this->fromAddress = $tsSettings['mail']['default']['from'];
}
if ($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']) {
$this->fromName = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName'];
}
$this->mailMessage->setFrom($this->fromAddress, $this->fromName);
$this->bccAddresses = GeneralUtility::trimExplode(',', $tsSettings['mail']['default']['bcc']);
$this->ccAddresses = GeneralUtility::trimExplode(',', $tsSettings['mail']['default']['cc']);

Torsten Oppermann
committed
foreach ($this->bccAddresses as $index => $email) {
if (!\filter_var($email, FILTER_VALIDATE_EMAIL)) {

Torsten Oppermann
committed
unset($this->bccAddresses[$index]);
}
}
foreach ($this->ccAddresses as $index => $email) {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
unset($this->ccAddresses[$index]);
}
}
if (\count($this->bccAddresses) > 0) {

Torsten Oppermann
committed
$this->mailMessage->setBcc($this->bccAddresses);
}
if (\count($this->ccAddresses) > 0) {

Torsten Oppermann
committed
$this->mailMessage->setCc($this->ccAddresses);
}
Stefan Galinski
committed
/**
* @param string $fromName
*/
public function setFromName($fromName) {
Stefan Galinski
committed
$this->fromName = $fromName;
}
/**
* Provides translation for the marker data type
*
* @param string $markerType
*/
public static function getReadableMarkerType($markerType) {
Stefan Galinski
committed
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
switch ($markerType) {
case self::MARKER_TYPE_STRING :
LocalizationUtility::translate('backend.marker.type.string', 'sg_mail');
break;
case self::MARKER_TYPE_ARRAY :
LocalizationUtility::translate('backend.marker.type.array', 'sg_mail');
break;
case self::MARKER_TYPE_OBJECT :
LocalizationUtility::translate('backend.marker.type.object', 'sg_mail');
break;
case self::MARKER_TYPE_FILE:
LocalizationUtility::translate('backend.marker.type.file', 'sg_mail');
break;
default:
LocalizationUtility::translate('backend.marker.type.mixed', 'sg_mail');
}
}
/**
* @param string $toAddresses
* @return MailTemplateService
*/
public function setToAddresses($toAddresses): MailTemplateService {
$normalizedToAddresses = trim(preg_replace('~\x{00a0}~iu', ' ', $toAddresses));
$this->toAddresses = $normalizedToAddresses;
$addressesArray = GeneralUtility::trimExplode(',', $normalizedToAddresses, TRUE);
if (\count($addressesArray) > 1) {
$normalizedToAddresses = $addressesArray;
}
$this->mailMessage->setTo($normalizedToAddresses);
return $this;
}
/**
* @param string $fromAddress
* @param string $fromName
* @return MailTemplateService
*/
public function setFromAddress($fromAddress, $fromName = ''): MailTemplateService {
if ($fromAddress) {
$this->fromAddress = $fromAddress;
$this->mailMessage->setFrom($fromAddress, $fromName);
}
return $this;
}
/**
* @param string $ccAddresses
* @return MailTemplateService
*/
public function setCcAddresses($ccAddresses): MailTemplateService {
if ($ccAddresses) {
$this->ccAddresses = $ccAddresses;
$this->mailMessage->setCc(GeneralUtility::trimExplode(',', $this->ccAddresses));
}
return $this;
}
/**
* @param string $replyToAddress
* @return MailTemplateService
*/
public function setReplyToAddress($replyToAddress): MailTemplateService {
if ($replyToAddress) {
$this->replyToAddress = $replyToAddress;
$this->mailMessage->setReplyTo($replyToAddress);
}
return $this;
}
/**
* @param string $language
* @return MailTemplateService
*/
public function setLanguage($language): MailTemplateService {
$this->language = $language;
return $this;
}
/**
* @param boolean $ignoreMailQueue
* @return MailTemplateService
*/
public function setIgnoreMailQueue($ignoreMailQueue): MailTemplateService {
$this->ignoreMailQueue = $ignoreMailQueue;
return $this;
}
/**
* @param string $templateName
* @return MailTemplateService
*/
public function setTemplateName($templateName): MailTemplateService {
$this->templateName = $templateName;
return $this;
}
/**
* @param string $extensionKey
* @return MailTemplateService
*/
public function setExtensionKey($extensionKey): MailTemplateService {
$this->extensionKey = $extensionKey;
return $this;
}
Fabian Galinski
committed
/**
* @param array $markers
* @return MailTemplateService
*/
public function addMarkers(array $markers): MailTemplateService {
$this->setMarkers(\array_merge($this->markers, $markers));
return $this;
}
Stefan Galinski
committed
/**
* @param array $markers
* @return MailTemplateService
*/
public function setMarkers(array $markers): MailTemplateService {
$this->markers = $markers;
foreach ($markers as $key => $currentMarker) {
if (!\is_array($currentMarker) || !isset($currentMarker['markerLabel'])) {
continue;
}
$this->markerLabels[$key] = $currentMarker['markerLabel'];
}
Stefan Galinski
committed
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
return $this;
}
/**
* @param string $bccAddresses
* @return MailTemplateService
*/
public function setBccAddresses($bccAddresses): MailTemplateService {
if ($bccAddresses) {
$this->bccAddresses = $bccAddresses;
$this->mailMessage->setBcc(GeneralUtility::trimExplode(',', $this->bccAddresses));
}
return $this;
}
/**
* @param int $priority
* @return MailTemplateService
*/
public function setPriority($priority): MailTemplateService {
$this->priority = $priority;
return $this;
}
/**
* @param Swift_OutputByteStream $data
* @param string $filename
* @param string $contentType
* @return MailTemplateService
*/
public function addAttachment($data, $filename, $contentType): MailTemplateService {
$attachment = Swift_Attachment::newInstance()
->setFilename($filename)
->setContentType($contentType)
->setBody($data);
$this->mailMessage->attach($attachment);
return $this;
}
/**
* Adds a file resource as attachment
*
Fabian Galinski
committed
* @param FileReference $fileReference
* @param File $file
Stefan Galinski
committed
*
* @return MailTemplateService
* @throws \TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException
Stefan Galinski
committed
*/
Fabian Galinski
committed
public function addFileResourceAttachment(
FileReference $fileReference = NULL, File $file = NULL
): MailTemplateService {
if (!$file) {
if (!$fileReference) {
return $this;
}
$originalResource = $fileReference->getOriginalResource();
if (!$originalResource) {
return $this;
}
$file = $originalResource->getOriginalFile();
if (!$file) {
return $this;
}
}
$coreFileReferenceMailFile = $this->resourceFactory->createFileReferenceObject(
[
Fabian Galinski
committed
'uid_local' => $file->getUid(),
'table_local' => 'sys_file',
'uid' => uniqid('NEW_MAIL', TRUE)
]
);
$newFileReference = GeneralUtility::makeInstance(FileReference::class);
$newFileReference->setOriginalResource($coreFileReferenceMailFile);
$this->markers[] = $newFileReference;
Stefan Galinski
committed
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
return $this;
}
/**
* @return MailMessage
*/
public function getMailMessage(): MailMessage {
return $this->mailMessage;
}
/**
* set the page id from which this was called
*
* @param int $pid
* @return MailTemplateService
*/
public function setPid($pid): MailTemplateService {
$this->pid = (int) $pid;
return $this;
}
/**
* Checks if a template is blacklisted for a given siteroot id
*
* @param string $extensionKey
* @param string $templateName
* @param int $siteRootId
* @return boolean
* @throws \InvalidArgumentException
* @throws \BadFunctionCallException
* @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
*/
public static function isTemplateBlacklisted($extensionKey, $templateName, $siteRootId): bool {
$nonBlacklistedTemplates = BackendService::getNonBlacklistedTemplates($siteRootId);
if ($nonBlacklistedTemplates[$extensionKey]) {
return $nonBlacklistedTemplates[$extensionKey][$templateName] ? FALSE : TRUE;
}
return TRUE;
}
/**
* @return string
*/
public function getSubject(): string {
return $this->subject;
}
/**
* @param string $subject
*/
public function setSubject(string $subject) {
Stefan Galinski
committed
$this->subject = $subject;
}
/**
* @return string
*/
public function getOverwrittenEmailBody(): string {
return $this->overwrittenEmailBody;
}
/**
* @param string $overwrittenEmailBody
*/
public function setOverwrittenEmailBody(string $overwrittenEmailBody) {
$this->overwrittenEmailBody = $overwrittenEmailBody;
}
/**
* Return default markers for sg_mail
*
* @param string $translationKey
* @param array $marker
* @param string $extensionKey
* @return array
*/
public static function getDefaultTemplateMarker($translationKey, array $marker, $extensionKey = 'sg_mail'): array {
$languagePath = 'LLL:EXT:' . $extensionKey . '/Resources/Private/Language/locallang.xlf:' . $translationKey;
// Need the key for translations
if (\trim($extensionKey) === '') {
return [];
}
$generatedMarker = [];
foreach ($marker as $markerName) {
$generatedMarker[] = [
'marker' => $markerName,
'value' => $languagePath . '.example.' . $markerName,
'description' => $languagePath . '.description.' . $markerName,
'backend_translation_key' => $translationKey . '.example.' . $markerName,
'extension_key' => $extensionKey
];
}
return $generatedMarker;
}
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
/**
* Set preview markers for the template editor
*
* @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
*/
public function setPreviewMarkers() {
$previewMarker = [];
// get default template content from register array
$registerService = GeneralUtility::makeInstance(RegisterService::class);
/** @var array $markerArray */
$markerArray = $registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['marker'];
foreach ($markerArray as $marker) {
$markerPath = GeneralUtility::trimExplode('.', $marker['marker']);
$temporaryMarkerArray = [];
foreach (\array_reverse($markerPath) as $index => $markerPathSegment) {
if ($index === 0) {
if ($marker['markerLabel']) {
$markerPathSegment = $marker['markerLabel'];
}
if ($marker['backend_translation_key']) {
$temporaryMarkerArray[$markerPathSegment] = LocalizationUtility::translate(
$marker['backend_translation_key'], $marker['extension_key']
);
} else {
$temporaryMarkerArray[$markerPathSegment] = $marker['value'];
}
} else {
$temporaryMarkerArray = [$markerPathSegment => $temporaryMarkerArray];
}
}
/** @noinspection SlowArrayOperationsInLoopInspection */
$previewMarker = \array_merge_recursive($previewMarker, $temporaryMarkerArray);
}
$this->setMarkers($previewMarker);
}

Torsten Oppermann
committed
* Send the Email

Torsten Oppermann
committed
*
* @param bool $isPreview
* @return bool email was sent or added to mail queue successfully?

Torsten Oppermann
committed
* @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
* @throws \InvalidArgumentException
* @throws \BadFunctionCallException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
Stefan Galinski
committed
* @throws \Exception
public function sendEmail($isPreview = FALSE): bool {
Stefan Galinski
committed
/** @var TypoScriptFrontendController $typoscriptFrontendController */
$typoscriptFrontendController = $GLOBALS['TSFE'];
$pageUid = (int) $typoscriptFrontendController->id;
} else {
$pageUid = (int) GeneralUtility::_GP('id');
}
if ($this->pid) {
$pageUid = $this->pid;
if ($pageUid === 0) {

Torsten Oppermann
committed
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
'pages'

Torsten Oppermann
committed
$rootPageRows = $queryBuilder->select('*')
->from('pages')

Torsten Oppermann
committed
->where(
$queryBuilder->expr()->eq(
'is_siteroot', 1
)
)
->andWhere(
$queryBuilder->expr()->eq(
'hidden', 0
)
)
->execute()->fetchAll();
if ($rootPageRows && \count($rootPageRows)) {
$pageUid = (int) $rootPageRows[0]['uid'];
}
$siteRootId = BackendService::getSiteRoot($pageUid);

Torsten Oppermann
committed
$isTemplateBlacklisted = self::isTemplateBlacklisted($this->extensionKey, $this->templateName, $siteRootId);
if ($isTemplateBlacklisted) {
// @TODO throw error or log ?
return FALSE;

Torsten Oppermann
committed
/** @var Template $template */
$template = $this->templateRepository->findOneByTemplate(

Torsten Oppermann
committed
$this->extensionKey, $this->templateName, $this->language, $siteRootId

Torsten Oppermann
committed
if ($template === NULL) {
$template = $this->templateRepository->findOneByTemplate(
$this->extensionKey, $this->templateName, 'default', $siteRootId
);
}

Torsten Oppermann
committed
// if there is a template, prefer those values
if ($template) {
$this->loadTemplateValues($template);
}
// get default template content from register array
$registerService = GeneralUtility::makeInstance(RegisterService::class);
Stefan Galinski
committed
$defaultTemplateContent =
$registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['templateContent'];
// If there is no template for this language, use the default template
if ($template === NULL) {
if ($defaultTemplateContent === NULL) {
Stefan Galinski
committed
$templatePath =
$registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['templatePath'];
// only standard template file is considered since version 4.1
$defaultTemplateFile = $templatePath . 'template.html';
if (\file_exists($defaultTemplateFile)) {
$defaultTemplateContent = \file_get_contents($defaultTemplateFile);

Torsten Oppermann
committed
} else {
// use configured default html template
/** @var TypoScriptSettingsService $typoScriptSettingsService */
$typoScriptSettingsService = $this->objectManager->get(TypoScriptSettingsService::class);
$tsSettings = $typoScriptSettingsService->getSettings(0, 'tx_sgmail');
$defaultTemplateFile = GeneralUtility::getFileAbsFileName(
$tsSettings['mail']['defaultHtmlTemplate']
);
if (\file_exists($defaultTemplateFile)) {
$defaultTemplateContent = \file_get_contents($defaultTemplateFile);
return FALSE;

Torsten Oppermann
committed
}
} elseif (\filter_var($template->getToAddress(), FILTER_VALIDATE_EMAIL)) {
$this->setToAddresses(\trim($template->getToAddress()));
/** @var StandaloneView $emailView */

Markus Guenther
committed
$emailView = $this->objectManager->get(StandaloneView::class);
$emailView->assignMultiple($this->markers);
$emailView->assign('all_fields', $this->getAllMarker($this->markers));
$overwrittenEmailBody = $this->getOverwrittenEmailBody();
$overwrittenSubject = '';
if ($this->subject !== '' && $this->subject !== NULL) {
$overwrittenSubject = $this->subject;
}
// parse markers
$emailView->setTemplateSource(
\trim(empty($overwrittenSubject) ? $template->getSubject() : $overwrittenSubject)
);
$subject = $emailView->render();
$emailView->setTemplateSource(
$this->getTemplateSource(
$template->getFromMail(),
$template->getLayout(), $siteRootId
)
);
$fromMail = $emailView->render();
$emailView->setTemplateSource(
$this->getTemplateSource(
empty($overwrittenEmailBody) ? $template->getContent() : $overwrittenEmailBody,
$template->getLayout(), $siteRootId
)
$subject = $registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['subject'];
if (\is_array($subject)) {
$subject = \trim(
$registerService->getRegisterArray()
[$this->extensionKey][$this->templateName]['subject'][$this->language]

Torsten Oppermann
committed
}
$emailView->setTemplateSource(empty($overwrittenSubject) ? $subject : $overwrittenSubject);
$subject = $emailView->render();
$emailView->setTemplateSource(
$this->getTemplateSource(
$template->getFromMail(),
0, $siteRootId
)
);
$fromMail = $emailView->render();
$emailView->setTemplateSource(
$this->getTemplateSource(
empty($overwrittenEmailBody) ? $defaultTemplateContent : $overwrittenEmailBody,
0, $siteRootId
)
}
$this->mailMessage->setSubject($subject);
$this->setFromAddress($fromMail);

Torsten Oppermann
committed
Stefan Galinski
committed
// insert <br> tags, but replace every instance of three or more successive breaks with just two.
$emailBody = $emailView->render();
$emailBody = \nl2br($emailBody);
$emailBody = \preg_replace('/(<br[\s]?[\/]?>[\s]*){3,}/', '<br><br>', $emailBody);
Stefan Galinski
committed
$mail = $this->addMailToMailQueue(
$this->extensionKey, $this->templateName, $subject, $emailBody, $this->priority,
0, 0, $this->language, $siteRootId
);
if ($this->ignoreMailQueue) {
$success = $this->sendMailFromQueue($mail->getUid());
}
if ($isPreview) {
$mailRepository = $this->objectManager->get(MailRepository::class);
$mailRepository->remove($mail);
$this->persistenceManager->persistAll();

Torsten Oppermann
committed
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
/**
* Combines the template content with the layout and returns the result
*
* @param string $content
* @param int $layoutUid
* @param int $siteRootId
* @return string
*/
private function getTemplateSource(string $content, int $layoutUid, int $siteRootId): string {
if ($layoutUid === -1) {
return $content;
}
$languageUid = 0;
if ($this->language !== self::DEFAULT_LANGUAGE) {
$languageUid = (int) array_search($this->language, $this->getAvailableLanguages(), TRUE);
}
$frontendSimulated = FALSE;
if (!isset($GLOBALS['TSFE'])) {
$frontendSimulated = TRUE;
$GLOBALS['TSFE'] = new TypoScriptFrontendController(NULL, $siteRootId, 0);
}
/** @var array $layout */
$layout = $this->layoutRepository->findByUidOrDefault($layoutUid, $siteRootId, $languageUid);
if ($frontendSimulated) {
unset($GLOBALS['TSFE']);
}
if ($layout === NULL) {
return $content;
}
return str_replace('###CONTENT###', $content, $layout['content']);
}
/**
* Returns the list of avalilable translation languages
*
* @return array
*/
private function getAvailableLanguages(): array {
$out = [0 => ''];
if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '9.0.0', '<')) {
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
'sys_language'
);
$rows = $queryBuilder->select('*')
->from('sys_language')->execute()->fetchAll();
foreach ($rows as $row) {
$out[(int) $row['uid']] = $row['language_isocode'];
}
} else {
try {
$site = GeneralUtility::makeInstance(SiteMatcher::class)->matchByPageId(0);
} catch (\Exception $exception) {
return [0 => ''];
}
$availableLanguages = $site->getLanguages();
$out = [];
foreach ($availableLanguages as $language) {
$languageId = $language->getLanguageId();
if ($languageId < 0) {
continue;
}
$out[$language->getLanguageId()] = strtolower($language->getTwoLetterIsoCode());
}
}
return $out;
}
* Adds a new mail to the mail queue.
* @param string $extensionKey
* @param string $templateName

Torsten Oppermann
committed
* @param int $sendingTime

Torsten Oppermann
committed
* @param int $lastSendingTime
* @param string $language
* @param int $pid
* @throws \InvalidArgumentException
* @throws \BadFunctionCallException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
* @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException

Torsten Oppermann
committed
private function addMailToMailQueue(
$extensionKey, $templateName, $subject, $emailBody, $priority, $sendingTime = 0,

Torsten Oppermann
committed
$lastSendingTime = 0, $language = self::DEFAULT_LANGUAGE, $pid = 0

Markus Guenther
committed
$mail = $this->objectManager->get(Mail::class);
$mail->setPid($pid);
$mail->setExtensionKey($extensionKey);
$mail->setTemplateName($templateName);
$mail->setLanguage($language);
$mail->setBlacklisted(self::isTemplateBlacklisted($extensionKey, $templateName, $pid));
$mail->setFromAddress($this->fromAddress);
$mail->setFromName($this->fromName);
$mail->setToAddress($this->toAddresses);
$mail->setMailSubject($subject);
$mail->setPriority($priority);
$mail->setBccAddresses($this->bccAddresses);
$mail->setCcAddresses($this->ccAddresses);

Torsten Oppermann
committed
$mail->setSendingTime($sendingTime);

Torsten Oppermann
committed
$mail->setLastSendingTime($lastSendingTime);
$mail->setReplyTo($this->replyToAddress);
foreach ($this->markers as $marker) {
if ($marker instanceof FileReference) {
$mail->addAttachment($marker);
}
}

Markus Guenther
committed
$mailRepository = $this->objectManager->get(MailRepository::class);
$mailRepository->add($mail);
$this->persistenceManager->persistAll();
/**
* Send a Mail from the queue, identified by its id
*
* @param int $uid
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
Stefan Galinski
committed
* @throws \Exception
public function sendMailFromQueue($uid): bool {
$mailRepository = $this->objectManager->get(MailRepository::class);
/** @var Mail $mailToSend */
$mailToSend = $mailRepository->findOneByUid($uid);
if (!$mailToSend || $mailToSend->getBlacklisted()) {
return FALSE;
}
$this->mailMessage->setBody($mailToSend->getMailBody(), 'text/html');
$plaintextService = GeneralUtility::makeInstance(PlaintextService::class);
$plaintextBody = $plaintextService->makePlain($mailToSend->getMailBody());
$this->mailMessage->addPart($plaintextBody, 'text/plain');
$toAddresses = \trim($mailToSend->getToAddress());
$addressesArray = GeneralUtility::trimExplode(',', $toAddresses, TRUE);
if (\count($addressesArray) > 1) {
$toAddresses = $addressesArray;
}
$this->mailMessage->setTo($toAddresses);
$this->mailMessage->setFrom($mailToSend->getFromAddress(), $mailToSend->getFromName());
$this->mailMessage->setSubject($mailToSend->getMailSubject());

Torsten Oppermann
committed
if ($mailToSend->getBccAddresses()) {
$this->mailMessage->setBcc(GeneralUtility::trimExplode(',', $mailToSend->getBccAddresses()));
}

Torsten Oppermann
committed
if ($mailToSend->getCcAddresses()) {
$this->mailMessage->setCc(GeneralUtility::trimExplode(',', $mailToSend->getCcAddresses()));
}

Torsten Oppermann
committed
if ($mailToSend->getReplyTo()) {
$this->mailMessage->setReplyTo($mailToSend->getReplyTo());
}
$attachments = $mailToSend->getAttachments();
if ($attachments->count() > 0) {
foreach ($attachments as $attachment) {
/**
* @var FileReference $attachment
*/
$file = $attachment->getOriginalResource()->getOriginalFile();
$this->mailMessage->attach(
\Swift_Attachment::newInstance($file->getContents(), $file->getName(), $file->getMimeType())
);
$dateTime = new DateTime();
if ((int) $mailToSend->getSendingTime() === 0) {
$mailToSend->setSendingTime($dateTime->getTimestamp());
}
$mailToSend->setLastSendingTime($dateTime->getTimestamp());
$success = $this->mailMessage->send();
if ($success) {
$mailRepository->update($mailToSend);
$this->persistenceManager->persistAll();
} else {
$this->mailMessage->getFailedRecipients();
}
return $success;

Torsten Oppermann
committed
/**
* use all values from the given template
*
* @param Template $template
*/
private function loadTemplateValues($template) {
$fromName = \trim($template->getFromName());
if ($fromName === '') {