diff --git a/Classes/Command/SendMailCommandController.php b/Classes/Command/SendMailCommandController.php index e1c134d1a2d2f8952b5d531c81b431c393ec97ec..e751533cbde301d22c94c7a6de55c3149b17a56d 100644 --- a/Classes/Command/SendMailCommandController.php +++ b/Classes/Command/SendMailCommandController.php @@ -27,6 +27,7 @@ namespace SGalinski\SgMail\Command; ***************************************************************/ use SGalinski\SgMail\Domain\Model\Mail; +use SGalinski\SgMail\Service\PlaintextService; use TYPO3\CMS\Core\Mail\MailMessage; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Controller\CommandController; @@ -85,7 +86,11 @@ class SendMailCommandController extends CommandController { if (count($bccAddresses)) { $mailMessage->setBcc($bccAddresses); } + $mailMessage->setBody($mailBody, 'text/html'); + $plaintextService = GeneralUtility::makeInstance(PlaintextService::class); + $plaintextBody = $plaintextService->makePlain($mailBody); + $mailMessage->addPart($plaintextBody, 'text/plain'); try { $mailMessage->send(); diff --git a/Classes/Service/MailTemplateService.php b/Classes/Service/MailTemplateService.php index 8752bf3cb1547a09acf657d1af46bd78e1eec78d..602a6bbfc4ec5d1ef98d8ad9839eb7675857b71b 100644 --- a/Classes/Service/MailTemplateService.php +++ b/Classes/Service/MailTemplateService.php @@ -355,12 +355,15 @@ class MailTemplateService { // insert <br /> tags, but replace every instance of three or more successive breaks with just two. $emailBody = nl2br($emailBody); $emailBody = preg_replace('/(<br[\s]?[\/]?>[\s]*){3,}/', '<br /><br />', $emailBody); + $isTemplateBlacklisted = self::isTemplateBlacklisted( $this->extensionKey, $this->templateName, $siteRootId ); if ($this->ignoreMailQueue && !$isTemplateBlacklisted) { - $this->mailMessage->setBody($emailBody, 'text/html'); + $plaintextService = GeneralUtility::makeInstance(PlaintextService::class); + $plainTextBody = $plaintextService->makePlain($emailBody); + $this->mailMessage->addPart($plainTextBody, 'text/plain'); $this->mailMessage->send(); $dateTime = new DateTime(); $currentTimestamp = $dateTime->getTimestamp(); @@ -444,6 +447,9 @@ class MailTemplateService { if ($mailToSend && !$mailToSend->getBlacklisted()) { $this->mailMessage->setBody($mailToSend->getMailBody(), 'text/html'); + $plaintextService = GeneralUtility::makeInstance(PlaintextService::class); + $plaintextBody = $plaintextService->makePlain($mailToSend->getMailBody()); + $this->mailMessage->addPart($plaintextBody, 'text/plain'); $this->mailMessage->setTo(trim($mailToSend->getToAddress())); $this->mailMessage->setFrom($mailToSend->getFromAddress(), $mailToSend->getFromName()); $this->mailMessage->setSubject($mailToSend->getMailSubject()); diff --git a/Classes/Service/PlaintextService.php b/Classes/Service/PlaintextService.php new file mode 100644 index 0000000000000000000000000000000000000000..6ce872f9b259a0f9305740c981b3d77c8c4d00a9 --- /dev/null +++ b/Classes/Service/PlaintextService.php @@ -0,0 +1,167 @@ +<?php +/** + * Copyright notice + * + * (c) in2code <info@in2code.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 2 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! + */ + +declare(strict_types=1); +namespace SGalinski\SgMail\Service; + +/** + * Class PlaintextService + */ +class PlaintextService +{ + + /** + * Function makePlain() removes html tags and add linebreaks + * Easy generate a plain email bodytext from a html bodytext + * + * @param string $content HTML Mail bodytext + * @return string $content + */ + public function makePlain($content) + { + $content = $this->removeInvisibleElements($content); + $content = $this->removeLinebreaksAndTabs($content); + $content = $this->addLineBreaks($content); + $content = $this->addSpaceToTableCells($content); + $content = $this->extractLinkForPlainTextContent($content); + $content = $this->removeTags($content); + $array = [ + '<br >', + '<br>', + '<br/>', + '<br />' + ]; + return trim(str_replace($array, PHP_EOL, $content)); + } + + /** + * Remove all invisible elements + * + * @param string $content + * @return string + */ + protected function removeInvisibleElements($content) + { + $content = preg_replace( + [ + '/<head[^>]*?>.*?<\/head>/siu', + '/<style[^>]*?>.*?<\/style>/siu', + '/<script[^>]*?>.*?<\/script>/siu', + '/<object[^>]*?>.*?<\/object>/siu', + '/<embed[^>]*?>.*?<\/embed>/siu', + '/<applet[^>]*?>.*?<\/applet>/siu', + '/<noframes[^>]*?>.*?<\/noframes>/siu', + '/<noscript[^>]*?>.*?<\/noscript>/siu', + '/<noembed[^>]*?>.*?<\/noembed>/siu', + ], + [ + '', '', '', '', '', '', '', '', '' + ], + $content + ); + return $content; + } + + /** + * Remove linebreaks and tabs + * + * @param string $content + * @return string + */ + protected function removeLinebreaksAndTabs($content) + { + $content = trim(str_replace(["\n", "\r", "\t"], '', $content)); + return $content; + } + + /** + * add linebreaks on some parts (</p> => </p><br />) + * + * @param string $content + * @return array + */ + protected function addLineBreaks($content) + { + $tags2LineBreaks = [ + '</p>', + '</tr>', + '<ul>', + '</li>', + '</h1>', + '</h2>', + '</h3>', + '</h4>', + '</h5>', + '</h6>', + '</div>', + '</legend>', + '</fieldset>', + '</dd>', + '</dt>' + ]; + return str_replace($tags2LineBreaks, '</p><br />', $content); + } + + /** + * Add a space character to a table cell + * + * @param string $content + * @return string + */ + protected function addSpaceToTableCells($content) + { + return str_replace(['</td>', '</th>'], '</td> ', $content); + } + + /** + * Remove all tags but keep br and address + * + * @param string $content + * @return string + */ + protected function removeTags($content) + { + return strip_tags($content, '<br><address>'); + } + + /** + * Extract uri from href attributes and decode it + * + * replace links + * <a href="xyz">LINK</a> + * -> + * LINK [xyz] + * + * @param string $content + * @return string + */ + protected function extractLinkForPlainTextContent($content) + { + $pattern = '/<a[^>]+href\s*=\s*["\']([^"\']+)["\'][^>]*>(.*?)<\/a>/misu'; + return preg_replace_callback($pattern, function ($matches) { + return $matches[2] . ' [' . htmlspecialchars_decode($matches[1]) . ']'; + }, $content); + } +}