Commit 1051b0bd authored by Georgi Mateev's avatar Georgi Mateev
Browse files

[BUGFIX] 1604 Drastically improved sg_mail performance

parent 030ca7a8
......@@ -426,6 +426,8 @@ class NewsletterController extends ActionController {
$mailTemplateService->setOverwrittenFromMail($parameter['fromMail']);
$mailTemplateService->setSubject($parameter['subject']);
$mailTemplateService->setOverwrittenReplyTo($parameter['replyTo']);
$siteRootId = $mailTemplateService->getSiteRootId();
$templateObject = $mailTemplateService->getTemplate($siteRootId);
if (!$this->request->getArgument('sendRealEmails')) {
// Send test emails
......@@ -454,7 +456,7 @@ class NewsletterController extends ActionController {
'www' => ' www.example.com',
]
]);
$mailIsSend = $mailTemplateService->sendEmail(TRUE);
$mailIsSend = $mailTemplateService->sendEmail(TRUE, $templateObject);
}
} else {
......@@ -484,7 +486,8 @@ class NewsletterController extends ActionController {
$mailTemplateService->setToAddresses($recipient['email']);
$mailTemplateService->setMarkers(['user' => $recipient]);
// no real error handling here, one must check the MailQueue
$mailTemplateService->sendEmail(FALSE);
$mailTemplateService->sendEmail(FALSE, $templateObject);
} catch (\Exception $e) {
// Invalid email address could not be loaded to queue
$errorRecipients[] = $recipient['uid'] . ' - '
......
......@@ -181,7 +181,7 @@ class BackendService {
}
}
return $siteRoot['uid'];
return (int) $siteRoot['uid'];
}
/**
......
......@@ -202,6 +202,14 @@ class MailTemplateService {
* @var TYPO3\CMS\Core\Resource\ResourceFactory
*/
protected $resourceFactory;
/**
* @var string
*/
private $mailBodyToSend;
/**
* @var string
*/
private $subjectToSend;
/**
* MailTemplateService constructor.
......@@ -649,18 +657,11 @@ class MailTemplateService {
}
/**
* Send the Email
* Gets the current PageUid
*
* @param bool $isPreview
* @return bool email was sent or added to mail queue successfully?
* @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
* @throws \InvalidArgumentException
* @throws \BadFunctionCallException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
* @throws \Exception
* @return int
*/
public function sendEmail($isPreview = FALSE): bool {
$success = FALSE;
protected function getPageUid(): int {
if (TYPO3_MODE === 'FE') {
/** @var TypoScriptFrontendController $typoscriptFrontendController */
$typoscriptFrontendController = $GLOBALS['TSFE'];
......@@ -673,6 +674,7 @@ class MailTemplateService {
$pageUid = $this->pid;
}
//TODO: move to page repository
if ($pageUid === 0) {
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
'pages'
......@@ -695,14 +697,21 @@ class MailTemplateService {
$pageUid = (int) $rootPageRows[0]['uid'];
}
}
$siteRootId = BackendService::getSiteRoot($pageUid);
return $pageUid;
}
/**
* Get the template object
*
* @param int $siteRootId
* @return null|object|Template|FALSE
* @throws \Exception
*/
public function getTemplate(int $siteRootId) {
$isTemplateBlacklisted = self::isTemplateBlacklisted($this->extensionKey, $this->templateName, $siteRootId);
if ($isTemplateBlacklisted) {
// @TODO throw error or log ?
return FALSE;
throw new \Exception('The template is blacklisted');
}
/** @var Template $template */
$template = $this->templateRepository->findOneByTemplate(
$this->extensionKey, $this->templateName, $this->language, $siteRootId
......@@ -713,46 +722,55 @@ class MailTemplateService {
$this->extensionKey, $this->templateName, 'default', $siteRootId
);
}
return $template;
}
// get default template content from register array
$registerService = GeneralUtility::makeInstance(RegisterService::class);
/**
* Get the default content for this template
*
* @param $template
* @param $registerService
* @return bool|false|string
*/
protected function getDefaultTemplateContent($template, $registerService) {
$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) {
$templatePath =
$registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['templatePath'];
if (($template === NULL) && $defaultTemplateContent === NULL) {
$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);
} 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']
);
// only standard template file is considered since version 4.1
$defaultTemplateFile = $templatePath . 'template.html';
if (\file_exists($defaultTemplateFile)) {
$defaultTemplateContent = \file_get_contents($defaultTemplateFile);
} 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);
} else {
return FALSE;
}
return FALSE;
}
}
} elseif (\filter_var($template->getToAddress(), FILTER_VALIDATE_EMAIL)) {
$this->setToAddresses(\trim($template->getToAddress()));
}
if ($isPreview) {
$this->setIgnoreMailQueue(TRUE);
}
return $defaultTemplateContent;
}
/**
* @param $template
* @param $registerService
* @param $defaultTemplateContent
* @param $siteRootId
*/
protected function setMailValuesFromObjects($template, $registerService, $defaultTemplateContent, $siteRootId): void {
/** @var StandaloneView $emailView */
$emailView = $this->objectManager->get(StandaloneView::class);
$emailView->assignMultiple($this->markers);
......@@ -773,6 +791,7 @@ class MailTemplateService {
$layoutId = $template->getLayout();
$templateContent = $template->getContent();
$this->setSubjectToSend($subject);
} else {
$subject = $registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['subject'];
if (\is_array($subject)) {
......@@ -789,7 +808,8 @@ class MailTemplateService {
$layoutId = 0;
$templateContent = $defaultTemplateContent;
}
$this->setSubjectToSend($subject);
//TODO: is this object even in use somewhere?
$this->mailMessage->setSubject($subject);
if ($this->fromAddress === '') {
......@@ -869,16 +889,68 @@ class MailTemplateService {
// 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);
$this->mailBodyToSend = \preg_replace('/(<br[\s]?[\/]?>[\s]*){3,}/', '<br><br>', $emailBody);
}
/**
* Get site root ID
*
* @return int
*/
public function getSiteRootId(): int {
$pageUid = $this->getPageUid();
return BackendService::getSiteRoot($pageUid);
}
/**
* Send the Email
*
* @param bool $isPreview
* @param Template|null $template
* @return bool email was sent or added to mail queue successfully?
* @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
* @throws \TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
*/
public function sendEmail($isPreview = FALSE, Template $template = NULL): bool {
if ($isPreview) { //TODO: remove this from here
$this->setIgnoreMailQueue(TRUE);
}
$success = FALSE;
// Get page ID
$siteRootId = $this->getSiteRootId();
if ($template === NULL) {
// Get template
try {
$template = $this->getTemplate($siteRootId);
} catch (\Exception $e) {
return FALSE;
}
}
$registerService = GeneralUtility::makeInstance(RegisterService::class);
// get default template content from register array
$defaultTemplateContent = $this->getDefaultTemplateContent($template, $registerService);
// set the ToAddress if there are no placeholders in it
// TODO: does this belong here?
if ($template !== NULL && \filter_var($template->getToAddress(), FILTER_VALIDATE_EMAIL)) {
$this->setToAddresses(\trim($template->getToAddress()));
}
$this->setMailValuesFromObjects($template, $registerService, $defaultTemplateContent, $siteRootId);
$mail = $this->addMailToMailQueue(
$this->extensionKey, $this->templateName, $subject, $emailBody, $this->priority,
$this->extensionKey, $this->templateName, $this->getSubjectToSend(), $this->getMailBodyToSend(), $this->priority,
0, 0, $this->language, $siteRootId
);
if ($this->ignoreMailQueue) {
$success = $this->sendMailFromQueue($mail->getUid());
$success = $this->sendMailFromQueue($mail->getUid(), $mail);
}
//TODO: this can be avoided if the sending logic is decoupled from this function
if ($isPreview) {
$mailRepository = $this->objectManager->get(MailRepository::class);
$mailRepository->remove($mail);
......@@ -1017,17 +1089,20 @@ class MailTemplateService {
* Send a Mail from the queue, identified by its id
*
* @param int $uid
* @param null $mailToSend
* @return bool|NULL
* @throws \TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
* @throws \Exception
*/
public function sendMailFromQueue($uid): bool {
public function sendMailFromQueue($uid, $mailToSend = NULL): bool {
$mailRepository = $this->objectManager->get(MailRepository::class);
/** @var Mail $mailToSend */
$mailToSend = $mailRepository->findOneByUid($uid);
if (!$mailToSend || $mailToSend->getBlacklisted()) {
return FALSE;
if ($mailToSend === NULL) {
$mailToSend = $mailRepository->findOneByUid($uid);
if (!$mailToSend || $mailToSend->getBlacklisted()) {
return FALSE;
}
}
$this->mailMessage->setBody($mailToSend->getMailBody(), 'text/html');
......@@ -1165,6 +1240,34 @@ class MailTemplateService {
$this->overwrittenToAddresses = $overwrittenToAddresses;
}
/**
* @return string|string[]|null
*/
public function getMailBodyToSend() {
return $this->mailBodyToSend;
}
/**
* @param string|string[]|null $mailBodyToSend
*/
public function setMailBodyToSend($mailBodyToSend): void {
$this->mailBodyToSend = $mailBodyToSend;
}
/**
* @return string
*/
public function getSubjectToSend(): string {
return $this->subjectToSend;
}
/**
* @param string $subjectToSend
*/
public function setSubjectToSend(string $subjectToSend): void {
$this->subjectToSend = $subjectToSend;
}
/**
* Sets the fromMail property of the mailTemplateService.
* Checks validity and uses all available fallbacks
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment