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 { ...@@ -426,6 +426,8 @@ class NewsletterController extends ActionController {
$mailTemplateService->setOverwrittenFromMail($parameter['fromMail']); $mailTemplateService->setOverwrittenFromMail($parameter['fromMail']);
$mailTemplateService->setSubject($parameter['subject']); $mailTemplateService->setSubject($parameter['subject']);
$mailTemplateService->setOverwrittenReplyTo($parameter['replyTo']); $mailTemplateService->setOverwrittenReplyTo($parameter['replyTo']);
$siteRootId = $mailTemplateService->getSiteRootId();
$templateObject = $mailTemplateService->getTemplate($siteRootId);
if (!$this->request->getArgument('sendRealEmails')) { if (!$this->request->getArgument('sendRealEmails')) {
// Send test emails // Send test emails
...@@ -454,7 +456,7 @@ class NewsletterController extends ActionController { ...@@ -454,7 +456,7 @@ class NewsletterController extends ActionController {
'www' => ' www.example.com', 'www' => ' www.example.com',
] ]
]); ]);
$mailIsSend = $mailTemplateService->sendEmail(TRUE); $mailIsSend = $mailTemplateService->sendEmail(TRUE, $templateObject);
} }
} else { } else {
...@@ -484,7 +486,8 @@ class NewsletterController extends ActionController { ...@@ -484,7 +486,8 @@ class NewsletterController extends ActionController {
$mailTemplateService->setToAddresses($recipient['email']); $mailTemplateService->setToAddresses($recipient['email']);
$mailTemplateService->setMarkers(['user' => $recipient]); $mailTemplateService->setMarkers(['user' => $recipient]);
// no real error handling here, one must check the MailQueue // no real error handling here, one must check the MailQueue
$mailTemplateService->sendEmail(FALSE);
$mailTemplateService->sendEmail(FALSE, $templateObject);
} catch (\Exception $e) { } catch (\Exception $e) {
// Invalid email address could not be loaded to queue // Invalid email address could not be loaded to queue
$errorRecipients[] = $recipient['uid'] . ' - ' $errorRecipients[] = $recipient['uid'] . ' - '
......
...@@ -181,7 +181,7 @@ class BackendService { ...@@ -181,7 +181,7 @@ class BackendService {
} }
} }
return $siteRoot['uid']; return (int) $siteRoot['uid'];
} }
/** /**
......
...@@ -202,6 +202,14 @@ class MailTemplateService { ...@@ -202,6 +202,14 @@ class MailTemplateService {
* @var TYPO3\CMS\Core\Resource\ResourceFactory * @var TYPO3\CMS\Core\Resource\ResourceFactory
*/ */
protected $resourceFactory; protected $resourceFactory;
/**
* @var string
*/
private $mailBodyToSend;
/**
* @var string
*/
private $subjectToSend;
/** /**
* MailTemplateService constructor. * MailTemplateService constructor.
...@@ -649,18 +657,11 @@ class MailTemplateService { ...@@ -649,18 +657,11 @@ class MailTemplateService {
} }
/** /**
* Send the Email * Gets the current PageUid
* *
* @param bool $isPreview * @return int
* @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
*/ */
public function sendEmail($isPreview = FALSE): bool { protected function getPageUid(): int {
$success = FALSE;
if (TYPO3_MODE === 'FE') { if (TYPO3_MODE === 'FE') {
/** @var TypoScriptFrontendController $typoscriptFrontendController */ /** @var TypoScriptFrontendController $typoscriptFrontendController */
$typoscriptFrontendController = $GLOBALS['TSFE']; $typoscriptFrontendController = $GLOBALS['TSFE'];
...@@ -673,6 +674,7 @@ class MailTemplateService { ...@@ -673,6 +674,7 @@ class MailTemplateService {
$pageUid = $this->pid; $pageUid = $this->pid;
} }
//TODO: move to page repository
if ($pageUid === 0) { if ($pageUid === 0) {
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable( $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
'pages' 'pages'
...@@ -695,14 +697,21 @@ class MailTemplateService { ...@@ -695,14 +697,21 @@ class MailTemplateService {
$pageUid = (int) $rootPageRows[0]['uid']; $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); $isTemplateBlacklisted = self::isTemplateBlacklisted($this->extensionKey, $this->templateName, $siteRootId);
if ($isTemplateBlacklisted) { if ($isTemplateBlacklisted) {
// @TODO throw error or log ? throw new \Exception('The template is blacklisted');
return FALSE;
} }
/** @var Template $template */ /** @var Template $template */
$template = $this->templateRepository->findOneByTemplate( $template = $this->templateRepository->findOneByTemplate(
$this->extensionKey, $this->templateName, $this->language, $siteRootId $this->extensionKey, $this->templateName, $this->language, $siteRootId
...@@ -713,15 +722,22 @@ class MailTemplateService { ...@@ -713,15 +722,22 @@ class MailTemplateService {
$this->extensionKey, $this->templateName, 'default', $siteRootId $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 = $defaultTemplateContent =
$registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['templateContent']; $registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['templateContent'];
// If there is no template for this language, use the default template // If there is no template for this language, use the default template
if ($template === NULL) { if (($template === NULL) && $defaultTemplateContent === NULL) {
if ($defaultTemplateContent === NULL) {
$templatePath = $templatePath =
$registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['templatePath']; $registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['templatePath'];
...@@ -745,14 +761,16 @@ class MailTemplateService { ...@@ -745,14 +761,16 @@ class MailTemplateService {
} }
} }
} }
} elseif (\filter_var($template->getToAddress(), FILTER_VALIDATE_EMAIL)) { return $defaultTemplateContent;
$this->setToAddresses(\trim($template->getToAddress()));
}
if ($isPreview) {
$this->setIgnoreMailQueue(TRUE);
} }
/**
* @param $template
* @param $registerService
* @param $defaultTemplateContent
* @param $siteRootId
*/
protected function setMailValuesFromObjects($template, $registerService, $defaultTemplateContent, $siteRootId): void {
/** @var StandaloneView $emailView */ /** @var StandaloneView $emailView */
$emailView = $this->objectManager->get(StandaloneView::class); $emailView = $this->objectManager->get(StandaloneView::class);
$emailView->assignMultiple($this->markers); $emailView->assignMultiple($this->markers);
...@@ -773,6 +791,7 @@ class MailTemplateService { ...@@ -773,6 +791,7 @@ class MailTemplateService {
$layoutId = $template->getLayout(); $layoutId = $template->getLayout();
$templateContent = $template->getContent(); $templateContent = $template->getContent();
$this->setSubjectToSend($subject);
} else { } else {
$subject = $registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['subject']; $subject = $registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['subject'];
if (\is_array($subject)) { if (\is_array($subject)) {
...@@ -789,7 +808,8 @@ class MailTemplateService { ...@@ -789,7 +808,8 @@ class MailTemplateService {
$layoutId = 0; $layoutId = 0;
$templateContent = $defaultTemplateContent; $templateContent = $defaultTemplateContent;
} }
$this->setSubjectToSend($subject);
//TODO: is this object even in use somewhere?
$this->mailMessage->setSubject($subject); $this->mailMessage->setSubject($subject);
if ($this->fromAddress === '') { if ($this->fromAddress === '') {
...@@ -869,16 +889,68 @@ class MailTemplateService { ...@@ -869,16 +889,68 @@ class MailTemplateService {
// insert <br> tags, but replace every instance of three or more successive breaks with just two. // insert <br> tags, but replace every instance of three or more successive breaks with just two.
$emailBody = $emailView->render(); $emailBody = $emailView->render();
$emailBody = \nl2br($emailBody); $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( $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 0, 0, $this->language, $siteRootId
); );
if ($this->ignoreMailQueue) { 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) { if ($isPreview) {
$mailRepository = $this->objectManager->get(MailRepository::class); $mailRepository = $this->objectManager->get(MailRepository::class);
$mailRepository->remove($mail); $mailRepository->remove($mail);
...@@ -1017,18 +1089,21 @@ class MailTemplateService { ...@@ -1017,18 +1089,21 @@ class MailTemplateService {
* Send a Mail from the queue, identified by its id * Send a Mail from the queue, identified by its id
* *
* @param int $uid * @param int $uid
* @param null $mailToSend
* @return bool|NULL * @return bool|NULL
* @throws \TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException * @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); $mailRepository = $this->objectManager->get(MailRepository::class);
/** @var Mail $mailToSend */ /** @var Mail $mailToSend */
if ($mailToSend === NULL) {
$mailToSend = $mailRepository->findOneByUid($uid); $mailToSend = $mailRepository->findOneByUid($uid);
if (!$mailToSend || $mailToSend->getBlacklisted()) { if (!$mailToSend || $mailToSend->getBlacklisted()) {
return FALSE; return FALSE;
} }
}
$this->mailMessage->setBody($mailToSend->getMailBody(), 'text/html'); $this->mailMessage->setBody($mailToSend->getMailBody(), 'text/html');
$plaintextService = GeneralUtility::makeInstance(PlaintextService::class); $plaintextService = GeneralUtility::makeInstance(PlaintextService::class);
...@@ -1165,6 +1240,34 @@ class MailTemplateService { ...@@ -1165,6 +1240,34 @@ class MailTemplateService {
$this->overwrittenToAddresses = $overwrittenToAddresses; $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. * Sets the fromMail property of the mailTemplateService.
* Checks validity and uses all available fallbacks * 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