pluswerk/mail_logger

View on GitHub
Classes/Logging/LoggingTransport.php

Summary

Maintainability
A
25 mins
Test Coverage
<?php

declare(strict_types=1);

namespace Pluswerk\MailLogger\Logging;

use Pluswerk\MailLogger\Domain\Model\MailLog;
use Pluswerk\MailLogger\Domain\Model\TemplateBasedMailMessage;
use Pluswerk\MailLogger\Domain\Repository\MailLogRepository;
use Symfony\Component\Mailer\Envelope;
use Symfony\Component\Mailer\SentMessage;
use Symfony\Component\Mailer\Transport\TransportInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Part\AbstractMultipartPart;
use Symfony\Component\Mime\Part\AbstractPart;
use Symfony\Component\Mime\Part\TextPart;
use Symfony\Component\Mime\RawMessage;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;

class LoggingTransport implements TransportInterface, \Stringable
{
    public function __construct(protected TransportInterface $originalTransport)
    {
    }

    public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage
    {
        $this->fixTcaIfNotPresentIsUsedInInstallTool();

        $mailLogRepository = GeneralUtility::makeInstance(MailLogRepository::class);

        // write mail to log before send
        $mailLog = GeneralUtility::makeInstance(MailLog::class);
        $this->assignMailLog($mailLog, $message);
        $mailLogRepository->add($mailLog);
        GeneralUtility::makeInstance(PersistenceManager::class)->persistAll();

        $result = $this->originalTransport->send($message, $envelope);

        // write result to log after send
        $this->assignMailLog($mailLog, $message);
        $mailLog->setResult((string)(bool)$result);
        $mailLogRepository->update($mailLog);
        return $result;
    }

    public function __toString(): string
    {
        return $this->originalTransport->__toString();
    }

    protected function assignMailLog(MailLog $mailLog, RawMessage $message): void
    {
        if (!$message instanceof Email) {
            return;
        }

        $messageBody = $message->getBody();
        $mailLog->setMessage($this->getBodyAsHtml($messageBody));
        $mailLog->setSubject($message->getSubject());
        $mailLog->setMailFrom($this->addressesToString($message->getFrom()));
        $mailLog->setMailTo($this->addressesToString($message->getTo()));
        $mailLog->setMailCopy($this->addressesToString($message->getCc()));
        $mailLog->setMailBlindCopy($this->addressesToString($message->getBcc()));
        $mailLog->setHeaders($message->getHeaders()->toString());
        if ($message instanceof TemplateBasedMailMessage) {
            $mailLog->setTypoScriptKey($message->getTypoScriptKey());
        }
    }

    protected function getBodyAsHtml(AbstractPart $part): string
    {
        if ($part instanceof AbstractMultipartPart) {
            $messageString = '';
            foreach ($part->getParts() as $childPart) {
                $messageString .= $this->getBodyAsHtml($childPart);
                $messageString .= '----------------------------------------<br>';
            }

            return $messageString;
        }

        $body = $part instanceof TextPart && $part->getMediaType() === 'text' ? $part->getBody() : $part->asDebugString();
        $body = str_replace(["\t", "\r"], '', $body);
        if ($part->getMediaSubtype() === 'plain') {
            $body = str_replace(PHP_EOL, '<br>', $body);
        } else {
            $body = str_replace(PHP_EOL, '', $body);
        }

        return $body . '<br>';
    }

    /**
     * @param Address[] $addresses
     */
    protected function addressesToString(array $addresses): string
    {
        return implode(
            ', ',
            array_map(
                static fn(Address $address): string => $address->getName() . ' <' . $address->getAddress() . '>',
                $addresses
            )
        );
    }

    protected function fixTcaIfNotPresentIsUsedInInstallTool(): void
    {
        if (empty($GLOBALS['TCA']['tx_maillogger_domain_model_maillog'])) {
            $GLOBALS['TCA']['tx_maillogger_domain_model_maillog'] = require __DIR__ . '/../../Configuration/TCA/tx_maillogger_domain_model_maillog.php';
        }
    }
}