diff --git a/Classes/Command/SendMailCommandController.php b/Classes/Command/SendMailCommandController.php
index efb100b0554c1be5769e5a0422d91739d1358777..80f63032916d918cbf1916a326c80de131a07a9a 100644
--- a/Classes/Command/SendMailCommandController.php
+++ b/Classes/Command/SendMailCommandController.php
@@ -25,14 +25,11 @@
 
 namespace SGalinski\SgMail\Command;
 
-use SGalinski\SgMail\Domain\Model\Mail;
 use SGalinski\SgMail\Domain\Repository\MailRepository;
-use SGalinski\SgMail\Service\PlaintextService;
+use SGalinski\SgMail\Service\MailTemplateService;
 use Symfony\Component\Console\Input\InputArgument;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Output\OutputInterface;
-use TYPO3\CMS\Core\Mail\MailMessage;
-use TYPO3\CMS\Core\Resource\FileInterface;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use Symfony\Component\Console\Command\Command;
 use TYPO3\CMS\Core\Utility\VersionNumberUtility;
@@ -54,17 +51,10 @@ class SendMailCommandController extends Command {
 	}
 
 	/**
-	 * Execute the command
-	 *
-	 * @param InputInterface $input
-	 * @param OutputInterface $output
-	 * @return int
+	 * @return MailRepository
 	 * @throws Exception
-	 * @throws IllegalObjectTypeException
-	 * @throws UnknownObjectException
 	 */
-	public function execute(InputInterface $input, OutputInterface $output): int {
-		$sendCount = $input->getArgument('sendCount');
+	protected function getMailRepository(): MailRepository {
 		if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
 			$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
 			/** @var MailRepository $mailRepository */
@@ -73,93 +63,25 @@ class SendMailCommandController extends Command {
 			$mailRepository = GeneralUtility::makeInstance(MailRepository::class);
 		}
 
-		$mailsToSend = $mailRepository->findMailsToSend($sendCount);
-		foreach ($mailsToSend as $mailToSend) {
-			/** @var Mail $mailToSend */
-			$fromAddress = $mailToSend->getFromAddress();
-			$toAddresses = trim($mailToSend->getToAddress());
-			$addressesArray = GeneralUtility::trimExplode(',', $toAddresses, TRUE);
-			if (\count($addressesArray) > 1) {
-				$toAddresses = $addressesArray;
-			}
-			$ccAddresses = GeneralUtility::trimExplode(',', $mailToSend->getCcAddresses(), TRUE);
-			$bccAddresses = GeneralUtility::trimExplode(',', $mailToSend->getBccAddresses(), TRUE);
-			$mailSubject = $mailToSend->getMailSubject();
-			$mailBody = $mailToSend->getMailBody();
-
-			$mailToSend->setSendingTime(time());
-			$mailToSend->setLastSendingTime(time());
-
-			if (empty($fromAddress) || empty($toAddresses)) {
-				continue;
-			}
-			$mailRepository->update($mailToSend);
-
-			$mailMessage = GeneralUtility::makeInstance(MailMessage::class);
-			$mailMessage->setFrom($fromAddress, $mailToSend->getFromName());
-			$mailMessage->setTo($toAddresses);
-			$mailMessage->setSubject($mailSubject);
-			if (\count($ccAddresses)) {
-				$mailMessage->setCc($ccAddresses);
-			}
-
-			if (\count($bccAddresses)) {
-				$mailMessage->setBcc($bccAddresses);
-			}
-
-			$replyTo = $mailToSend->getReplyTo();
-			if ($replyTo) {
-				$mailMessage->setReplyTo($replyTo);
-			}
-
-			$plaintextService = GeneralUtility::makeInstance(PlaintextService::class);
-			$plaintextBody = $plaintextService->makePlain($mailBody);
-			if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
-				$mailMessage->setBody($mailBody, 'text/html');
-				$mailMessage->addPart($plaintextBody, 'text/plain');
-			} else {
-				$mailMessage->html($mailBody);
-				$mailMessage->text($plaintextBody);
-			}
-
-			$attachments = $mailToSend->getAttachments();
-			if ($attachments->count() > 0) {
-				foreach ($attachments as $attachment) {
-					try {
-						/** @var FileInterface $file */
-						$file = $attachment->getOriginalResource();
-						if (!$file) {
-							continue;
-						}
-
-						$file = $file->getOriginalFile();
-						if (!$file) {
-							continue;
-						}
-						if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
-							$mailMessage->attach(
-								\Swift_Attachment::newInstance(
-									$file->getContents(), $file->getName(), $file->getMimeType()
-								)
-							);
-						} else {
-							$mailMessage->attach($file->getContents(), $file->getName(), $file->getMimeType());
-						}
-					} catch (\Exception $exception) {
-						continue;
-					}
-				}
-			}
+		return $mailRepository;
+	}
 
-			try {
-				$mailMessage->send();
-			} catch (\Exception $exception) {
-				// Ignore that. We can't do much here in a misconfiguration case.
-			}
-		}
+	/**
+	 * Execute the command
+	 *
+	 * @param InputInterface $input
+	 * @param OutputInterface $output
+	 * @return int
+	 * @throws Exception
+	 * @throws IllegalObjectTypeException
+	 * @throws UnknownObjectException
+	 */
+	public function execute(InputInterface $input, OutputInterface $output): int {
+		$sendCount = $input->getArgument('sendCount');
 
-		// Important for command controllers that change data
-		$mailRepository->persist();
+		$mailsToSend = $this->getMailRepository()->findMailsToSend($sendCount)->toArray();
+		$mailService = GeneralUtility::makeInstance(MailTemplateService::class);
+		$mailService->sendMailsFromQueue($mailsToSend);
 		return 0;
 	}
 }
diff --git a/Classes/Controller/QueueController.php b/Classes/Controller/QueueController.php
index 3d4f1de86c04ebddd7d1a12b0a24bb21ea30752f..08342ef5c9a739ae31d3723c679c19af93d53660 100644
--- a/Classes/Controller/QueueController.php
+++ b/Classes/Controller/QueueController.php
@@ -25,6 +25,7 @@
 
 namespace SGalinski\SgMail\Controller;
 
+use SGalinski\SgMail\Domain\Model\Mail;
 use SGalinski\SgMail\Domain\Repository\MailRepository;
 use SGalinski\SgMail\Service\BackendService;
 use SGalinski\SgMail\Service\MailTemplateService;
@@ -32,16 +33,13 @@ use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException;
 use TYPO3\CMS\Core\Exception\SiteNotFoundException;
 use TYPO3\CMS\Core\Messaging\FlashMessage;
-use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
 use TYPO3\CMS\Core\Site\SiteFinder;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException;
 use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException;
 use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
 use TYPO3\CMS\Extbase\Object\Exception;
-use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException;
 use TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException;
-use TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException;
 use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
 
 /**
@@ -140,23 +138,35 @@ class QueueController extends AbstractController {
 	/**
 	 * send or resend a mail in the queue
 	 *
-	 * @param int $uid
-	 * @throws IllegalObjectTypeException
-	 * @throws ResourceDoesNotExistException
+	 * @param Mail $mail
 	 * @throws StopActionException
-	 * @throws UnknownObjectException
 	 */
-	public function sendMailAction(int $uid): void {
+	public function sendMailAction(Mail $mail): void {
 		$mailService = new MailTemplateService();
-		if ($mailService->sendMailFromQueue($uid)) {
-			$message = LocalizationUtility::translate('backend.success_mail_queue', 'sg_mail');
-			$this->addFlashMessage($message, '', FlashMessage::OK);
-		} else {
+		try {
+			$mailService->sendMailsFromQueue([$mail]);
+		} catch (\TYPO3\CMS\Core\Exception $exception) {
 			$message = LocalizationUtility::translate(
 				'backend.error_mail_queue',
 				'sg_mail'
 			);
 			$this->addFlashMessage($message, '', FlashMessage::ERROR);
+			$this->redirect('index', NULL, NULL, $this->request->getArguments());
+		}
+
+
+		if ($mail->getStatus() !== Mail::STATUS_ERROR) {
+			$this->addFlashMessage(
+				LocalizationUtility::translate('backend.success_mail_queue', 'sg_mail'),
+				'',
+				FlashMessage::OK
+			);
+		} else {
+			$this->addFlashMessage(
+				$mail->getErrorMessage(),
+				'',
+				FlashMessage::ERROR
+			);
 		}
 
 		$this->redirect('index', NULL, NULL, $this->request->getArguments());
@@ -165,12 +175,10 @@ class QueueController extends AbstractController {
 	/**
 	 * Preview for a mail
 	 *
-	 * @param int $uid
+	 * @param Mail $mail
 	 */
-	public function previewAction(int $uid): void {
-		$mailService = new MailTemplateService();
-		$mailToPreview = $mailService->getMailObjectByUid($uid);
-		$this->view->assign('mail', $mailToPreview);
+	public function previewAction(Mail $mail): void {
+		$this->view->assign('mail', $mail);
 	}
 
 	/**
diff --git a/Classes/Domain/Model/Mail.php b/Classes/Domain/Model/Mail.php
index 704e3279be285ab004a0bd4413c722e6b71f3aca..2f2c20f945f9b1b9ca1c747c645bd40a9c819080 100644
--- a/Classes/Domain/Model/Mail.php
+++ b/Classes/Domain/Model/Mail.php
@@ -39,6 +39,9 @@ class Mail extends AbstractEntity {
 	public const PRIORITY_MEDIUM = 100;
 	public const PRIORITY_HIGH = 150;
 	public const PRIORITY_HIGHEST = 200;
+	public const STATUS_PENDING = 'pending';
+	public const STATUS_SENT = 'sent';
+	public const STATUS_ERROR = 'error';
 
 	/**
 	 * @var string
@@ -120,6 +123,16 @@ class Mail extends AbstractEntity {
 	 */
 	protected $attachments;
 
+	/**
+	 * @var string
+	 */
+	protected $status = self::STATUS_PENDING;
+
+	/**
+	 * @var string
+	 */
+	protected $errorMessage = '';
+
 	/**
 	 * Mail constructor.
 	 */
@@ -371,4 +384,32 @@ class Mail extends AbstractEntity {
 	public function addAttachment(FileReference $attachment): void {
 		$this->attachments->attach($attachment);
 	}
+
+	/**
+	 * @return string
+	 */
+	public function getStatus(): string {
+		return $this->status;
+	}
+
+	/**
+	 * @param string $status
+	 */
+	public function setStatus(string $status): void {
+		$this->status = $status;
+	}
+
+	/**
+	 * @return string
+	 */
+	public function getErrorMessage(): string {
+		return $this->errorMessage;
+	}
+
+	/**
+	 * @param string $errorMessage
+	 */
+	public function setErrorMessage(string $errorMessage): void {
+		$this->errorMessage = $errorMessage;
+	}
 }
diff --git a/Classes/Service/MailTemplateService.php b/Classes/Service/MailTemplateService.php
index 9dd5f76a15b1e70efaaf23fae39ffee61c748f2b..d52ae23b7f605f833f359de58ef025ad96a1b8c0 100644
--- a/Classes/Service/MailTemplateService.php
+++ b/Classes/Service/MailTemplateService.php
@@ -25,39 +25,63 @@
 namespace SGalinski\SgMail\Service;
 
 use DateTime;
-use SGalinski\SgMail\Domain\Model\Layout;
 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 Symfony\Component\Mailer\Exception\TransportException;
-use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException;
 use TYPO3\CMS\Core\Mail\MailMessage;
+use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
 use TYPO3\CMS\Core\Resource\File;
+use TYPO3\CMS\Core\Resource\FileInterface;
+use TYPO3\CMS\Core\Resource\FileReference as CoreFileReference;
 use TYPO3\CMS\Core\Resource\ResourceFactory;
-use TYPO3\CMS\Core\Routing\SiteMatcher;
+use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
+use TYPO3\CMS\Core\Site\SiteFinder;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\VersionNumberUtility;
 use TYPO3\CMS\Extbase\Domain\Model\FileReference;
+use TYPO3\CMS\Extbase\Object\Exception;
 use TYPO3\CMS\Extbase\Object\ObjectManager;
+use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException;
+use TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException;
 use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
 use TYPO3\CMS\Fluid\View\StandaloneView;
+use function array_key_exists;
+use function array_merge;
+use function array_merge_recursive;
+use function array_reverse;
+use function count;
+use function file_exists;
+use function file_get_contents;
+use function filter_var;
+use function is_array;
+use function is_bool;
+use function is_object;
+use function is_string;
+use function method_exists;
+use function nl2br;
+use function preg_replace;
+use function str_replace;
+use function trim;
 
 /**
  * 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';
+	public const MARKER_TYPE_STRING = 'String';
+	public const MARKER_TYPE_ARRAY = 'Array';
+	public const MARKER_TYPE_OBJECT = 'Object';
+	public const MARKER_TYPE_FILE = 'File';
+	public const DEFAULT_LANGUAGE = 'default';
+	public const DEFAULT_TEMPLATE_PATH = 'Resources/Private/Templates/SgMail/';
+	public const CACHE_NAME = 'sg_mail_registerArrayCache';
+	public const CACHE_LIFETIME_IN_SECONDS = 86400;
+	public const REGISTER_FILE = 'Register.php';
+	public const CONFIG_PATH = 'Configuration/MailTemplates';
 
 	/**
 	 * @var array
@@ -68,16 +92,24 @@ class MailTemplateService {
 	 * @var array
 	 */
 	private static $mailObjectCache = [];
+
 	/**
-	 * @var \SGalinski\SgMail\Domain\Repository\TemplateRepository
+	 * @var TemplateRepository
 	 */
 	protected $templateRepository;
+
 	/**
-	 * @var \SGalinski\SgMail\Domain\Repository\LayoutRepository
+	 * @var LayoutRepository
 	 */
 	protected $layoutRepository;
+
+	/**
+	 * @var MailRepository
+	 */
+	protected $mailRepository;
+
 	/**
-	 * @var \TYPO3\CMS\Extbase\Object\ObjectManager
+	 * @var ObjectManager
 	 * @deprecated Not used since TYPO3 10
 	 */
 	protected $objectManager;
@@ -87,97 +119,95 @@ class MailTemplateService {
 	 */
 	protected $registerService;
 
-	/**
-	 * @var \TYPO3\CMS\Core\Resource\ResourceFactory
-	 */
-	protected $resourceFactory;
 	/**
 	 * @var string $toAddresses
 	 */
 	private $toAddresses = '';
+
 	/**
 	 * @var string $fromAddress
 	 */
 	private $fromAddress = '';
+
 	/**
 	 * @var string $ccAddresses
 	 */
 	private $ccAddresses;
+
 	/**
 	 * @var string $replyToAddress
 	 */
 	private $replyToAddress = '';
+
 	/**
-	 * @var string $language
+	 * @var SiteLanguage
 	 */
-	private $language = 'default';
+	private $siteLanguage;
+
 	/**
 	 * @var boolean $ignoreMailQueue
 	 */
 	private $ignoreMailQueue = TRUE;
-	/**
-	 * @var \TYPO3\CMS\Core\Mail\MailMessage $mailMessage
-	 */
-	private $mailMessage;
+
 	/**
 	 * @var string $templateName
 	 */
 	private $templateName;
+
 	/**
 	 * @var string $subject
 	 */
 	private $subject;
+
 	/**
 	 * @var string $overwrittenEmailBody
 	 */
 	private $overwrittenEmailBody = '';
+
 	/**
 	 * @var string $extensionKey
 	 */
 	private $extensionKey;
+
 	/**
 	 * @var array $markers
 	 */
 	private $markers;
+
 	/**
 	 * @var array $markerLabels
 	 */
 	private $markerLabels;
+
 	/**
 	 * @var string $bccAddresses
 	 */
 	private $bccAddresses;
+
 	/**
 	 * @var int
 	 */
 	private $priority = Mail::PRIORITY_LOWEST;
+
 	/**
 	 * @var int
 	 */
 	private $pid;
-	/**
-	 * @var string
-	 */
-	private $fromName = '';
-	/**
-	 * @var string
-	 */
-	private $mailBodyToSend;
 
 	/**
 	 * @var string
 	 */
-	private $subjectToSend;
+	private $fromName = '';
 
 	/**
 	 * @var string
 	 */
-	private $defaultFromAddress;
+	private $mailBodyToSend = '';
 
 	/**
 	 * @var string
 	 */
-	private $defaultFromName;
+	private $subjectToSend;
 
 	/**
 	 * MailTemplateService constructor.
@@ -186,58 +216,41 @@ class MailTemplateService {
 	 * @param string $extensionKey
 	 * @param array $markers
 	 * @param array $markerLabels
-	 * @throws \InvalidArgumentException
+	 * @throws Exception
 	 */
-	public function __construct($templateName = '', $extensionKey = '', $markers = [], $markerLabels = []) {
+	public function __construct(string $templateName = '', string $extensionKey = '', array $markers = [], array $markerLabels = []) {
 		$this->templateName = $templateName;
 		$this->extensionKey = $extensionKey;
 		$this->markers = $markers;
 		$this->markerLabels = $markerLabels;
 
 		$this->registerService = GeneralUtility::makeInstance(RegisterService::class);
-		$this->resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
-		$this->mailMessage = GeneralUtility::makeInstance(MailMessage::class);
-
 		if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0')) {
 			$this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
 			/** @var TypoScriptSettingsService $typoScriptSettingsService */
 			$typoScriptSettingsService = $this->objectManager->get(TypoScriptSettingsService::class);
-			/** @var TemplateRepository templateRepository */
-			$this->templateRepository = $this->objectManager->get(TemplateRepository::class);
-			/** @var LayoutRepository layoutRepository */
-			$this->layoutRepository = $this->objectManager->get(LayoutRepository::class);
 		} else {
 			$typoScriptSettingsService = GeneralUtility::makeInstance(TypoScriptSettingsService::class);
-			$this->templateRepository = GeneralUtility::makeInstance(TemplateRepository::class);
-			$this->layoutRepository = GeneralUtility::makeInstance(LayoutRepository::class);
 		}
 
 		$tsSettings = $typoScriptSettingsService->getSettings(0, 'tx_sgmail');
 		// 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)) {
+		if (filter_var($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'], FILTER_VALIDATE_EMAIL)) {
 			$this->fromAddress = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'];
-			$this->defaultFromAddress = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'];
+		} else if (!filter_var($tsSettings['mail']['default']['from'], FILTER_VALIDATE_EMAIL)) {
+			$this->fromAddress = 'noreply@example.org';
 		} else {
-			if (!\filter_var($tsSettings['mail']['default']['from'], FILTER_VALIDATE_EMAIL)) {
-				$this->fromAddress = 'noreply@example.org';
-				$this->defaultFromAddress = 'noreply@example.org';
-			} else {
-				$this->fromAddress = $tsSettings['mail']['default']['from'];
-				$this->defaultFromAddress = $tsSettings['mail']['default']['from'];
-			}
+			$this->fromAddress = $tsSettings['mail']['default']['from'];
 		}
 
 		if ($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']) {
 			$this->fromName = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName'];
-			$this->defaultFromName = $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']);
-
 		foreach ($this->bccAddresses as $index => $email) {
-			if (!\filter_var($email, FILTER_VALIDATE_EMAIL)) {
+			if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
 				unset($this->bccAddresses[$index]);
 			}
 		}
@@ -247,38 +260,6 @@ class MailTemplateService {
 				unset($this->ccAddresses[$index]);
 			}
 		}
-
-		if (\count($this->bccAddresses) > 0) {
-			$this->mailMessage->setBcc($this->bccAddresses);
-		}
-
-		if (\count($this->ccAddresses) > 0) {
-			$this->mailMessage->setCc($this->ccAddresses);
-		}
-	}
-
-	/**
-	 * Provides translation for the marker data type
-	 *
-	 * @param string $markerType
-	 */
-	public static function getReadableMarkerType($markerType) {
-		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');
-		}
 	}
 
 	/**
@@ -289,10 +270,10 @@ class MailTemplateService {
 	 * @param string $extensionKey
 	 * @return array
 	 */
-	public static function getDefaultTemplateMarker($translationKey, array $marker, $extensionKey = 'sg_mail'): array {
+	public static function getDefaultTemplateMarker(string $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) === '') {
+		if (trim($extensionKey) === '') {
 			return [];
 		}
 
@@ -310,78 +291,16 @@ class MailTemplateService {
 		return $generatedMarker;
 	}
 
-	/**
-	 * @param string $language
-	 * @return MailTemplateService
-	 */
-	public function setLanguage($language): MailTemplateService {
-		$this->language = $language;
-		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;
-	}
-
-	/**
-	 * @param array $markers
-	 * @return MailTemplateService
-	 */
-	public function addMarkers(array $markers): MailTemplateService {
-		$this->setMarkers(\array_merge($this->markers, $markers));
-		return $this;
-	}
-
-	/**
-	 * @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'];
-		}
-
-		return $this;
-	}
-
-	/**
-	 * @param int $priority
-	 * @return MailTemplateService
-	 */
-	public function setPriority($priority): MailTemplateService {
-		$this->priority = $priority;
-		return $this;
-	}
-
 	/**
 	 * Adds a file resource as attachment
 	 *
-	 * @param FileReference $fileReference
-	 * @param File $file
+	 * @param FileReference|null $fileReference
+	 * @param File|null $file
 	 *
 	 * @return MailTemplateService
-	 * @throws \TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException
 	 */
 	public function addFileResourceAttachment(
-		FileReference $fileReference = NULL, File $file = NULL
+		FileReference $fileReference = NULL, FileInterface $file = NULL
 	): MailTemplateService {
 		if (!$file) {
 			if (!$fileReference) {
@@ -399,7 +318,8 @@ class MailTemplateService {
 			}
 		}
 
-		$coreFileReferenceMailFile = $this->resourceFactory->createFileReferenceObject(
+		$coreFileReferenceMailFile = GeneralUtility::makeInstance(ResourceFactory::class)
+			->createFileReferenceObject(
 			[
 				'uid_local' => $file->getUid(),
 				'table_local' => 'sys_file',
@@ -414,53 +334,20 @@ class MailTemplateService {
 		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;
-	}
-
-	/**
-	 * @return string
-	 */
-	public function getSubject(): string {
-		return $this->subject;
-	}
-
-	/**
-	 * @param string $subject
-	 */
-	public function setSubject(string $subject) {
-		$this->subject = $subject;
-	}
-
 	/**
 	 * Set preview markers for the template editor
 	 *
-	 * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
+	 * @throws NoSuchCacheException
 	 */
-	public function setPreviewMarkers() {
-		$previewMarker = [];
+	public function setPreviewMarkers(): void {
+		$previewMarkers = [];
 
 		/** @var array $markerArray */
 		$markerArray = $this->registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['marker'];
-
 		foreach ($markerArray as $marker) {
 			$markerPath = GeneralUtility::trimExplode('.', $marker['marker']);
 			$temporaryMarkerArray = [];
-			foreach (\array_reverse($markerPath) as $index => $markerPathSegment) {
+			foreach (array_reverse($markerPath) as $index => $markerPathSegment) {
 				if ($index === 0) {
 					if ($marker['markerLabel']) {
 						$markerPathSegment = $marker['markerLabel'];
@@ -477,34 +364,27 @@ class MailTemplateService {
 					$temporaryMarkerArray = [$markerPathSegment => $temporaryMarkerArray];
 				}
 			}
-			/** @noinspection SlowArrayOperationsInLoopInspection */
-			$previewMarker = \array_merge_recursive($previewMarker, $temporaryMarkerArray);
+
+			$previewMarkers[] = $temporaryMarkerArray;
 		}
-		$this->setMarkers($previewMarker);
+
+		$this->setMarkers(array_merge_recursive(...$previewMarkers));
 	}
 
 	/**
 	 * Send the Email
 	 *
 	 * @param bool $isPreview
-	 * @param Template|null $template
+	 * @param bool $isNewsletter
 	 * @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, $isNewsletter = FALSE): bool {
-		if ($isPreview) { //TODO: remove this from here
-			$this->setIgnoreMailQueue(TRUE);
-		}
-		$success = FALSE;
-
-		// Get page ID
-		// TODO: this doesn't belong here. The API user needs to provide the UID
-		$siteRootId = $this->getSiteRootId();
+	 * @throws NoSuchCacheException
+	 * @throws ResourceDoesNotExistException
+	 * @throws IllegalObjectTypeException
+	 * @throws UnknownObjectException
+	 */
+	public function sendEmail(bool $isPreview = FALSE, bool $isNewsletter = FALSE): bool {
 		try {
-			$template = $this->getTemplate($siteRootId);
+			$template = $this->getTemplate();
 		} catch (\Exception $e) {
 			return FALSE;
 		}
@@ -519,136 +399,63 @@ class MailTemplateService {
 
 		// 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()));
+		if ($template !== NULL && filter_var($template->getToAddress(), FILTER_VALIDATE_EMAIL)) {
+			$this->setToAddresses(trim($template->getToAddress()));
 		}
 
-		$this->parseValuesForMail($template, $defaultTemplateContent, $siteRootId);
+		$this->parseValuesForMail($template, $defaultTemplateContent);
 
-		$mail = $this->addMailToMailQueue(
-			$this->extensionKey, $this->templateName, $this->getSubjectToSend(), $this->getMailBodyToSend(),
-			$this->priority,
-			0, 0, $this->language, $siteRootId
-		);
+		$mail = $this->addMailToMailQueue();
 		self::$mailObjectCache[$mail->getUid()] = $mail; // add it to cache to avoid extra DB queries
+		$success = FALSE;
 		if ($this->ignoreMailQueue) {
 			$success = $this->sendMailFromQueue($mail->getUid());
 		}
 
-		//TODO: this can be avoided if the sending logic is decoupled from this function
-		if ($isPreview) {
-			if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
-				/** @var MailRepository $mailRepository */
-				$mailRepository = $this->objectManager->get(MailRepository::class);
-			} else {
-				$mailRepository = GeneralUtility::makeInstance(MailRepository::class);
-			}
-
-			$mailRepository->remove($mail);
-			$mailRepository->persist();
-		}
-
 		return $success;
 	}
 
-	/**
-	 * @param boolean $ignoreMailQueue
-	 * @return MailTemplateService
-	 */
-	public function setIgnoreMailQueue($ignoreMailQueue): MailTemplateService {
-		$this->ignoreMailQueue = $ignoreMailQueue;
-		return $this;
-	}
-
-	/**
-	 * Get site root ID
-	 *
-	 * @return int
-	 */
-	public function getSiteRootId(): int {
-		$pageUid = $this->getPageUid();
-		return BackendService::getSiteRoot($pageUid);
-	}
-
-	/**
-	 * Gets the current PageUid
-	 *
-	 * @return int
-	 */
-	protected function getPageUid(): int {
-		if (TYPO3_MODE === 'FE') {
-			$pageUid = (int) $GLOBALS['TSFE']->id;
-		} else {
-			$pageUid = (int) GeneralUtility::_GP('id');
-		}
-
-		if ($this->pid) {
-			$pageUid = $this->pid;
-		}
-
-		if ($pageUid === 0) {
-			$pageUid = $this->getAnyRootPageUid();
-		}
-		return $pageUid;
-	}
-
-	/**
-	 * Gets the page uid of any root page in the page tree
-	 *
-	 * @return int
-	 */
-	private function getAnyRootPageUid() {
-		$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
-			'pages'
-		);
-		$rootPageRows = $queryBuilder->select('*')
-			->from('pages')
-			->where(
-				$queryBuilder->expr()->eq(
-					'is_siteroot', 1
-				)
-			)
-			->andWhere(
-				$queryBuilder->expr()->eq(
-					'hidden', 0
-				)
-			)
-			->execute()->fetchAll();
-
-		if ($rootPageRows && \count($rootPageRows)) {
-			$pageUid = (int) $rootPageRows[0]['uid'];
-		}
-		return $pageUid;
-	}
-
 	/**
 	 * Get the template object
 	 *
-	 * @param int $siteRootId
-	 * @return null|object|Template|FALSE
+	 * @return null|Template
 	 * @throws \Exception
 	 */
-	private function getTemplate($siteRootId) {
-		$isTemplateBlacklisted = $this->registerService->isTemplateBlacklisted($this->extensionKey, $this->templateName, $siteRootId);
+	private function getTemplate(): ?Template {
+		$isTemplateBlacklisted = $this->registerService->isTemplateBlacklisted(
+			$this->extensionKey,
+			$this->templateName,
+			$this->pid
+		);
 		if ($isTemplateBlacklisted) {
 			throw new \Exception('The template is blacklisted');
 		}
 
-		$templateHash = $this->getTemplateHash($this->extensionKey, $this->templateName, $siteRootId, $this->language);
-		if (isset(self::$templateObjectCache[$templateHash])
-			&& self::$templateObjectCache[$templateHash] instanceof Template) {
+		$templateHash = $this->getTemplateHash();
+		if (
+			isset(self::$templateObjectCache[$templateHash])
+			&& self::$templateObjectCache[$templateHash] instanceof Template
+		) {
 			return self::$templateObjectCache[$templateHash];
 		}
+
 		/** @var Template $template */
-		$template = $this->templateRepository->findOneByTemplate(
-			$this->extensionKey, $this->templateName, $this->language, $siteRootId
-		);
+		$template = $this->getTemplateRepository()->findByTemplateProperties(
+			$this->extensionKey, $this->templateName, [$this->siteLanguage], $this->pid
+		)->getFirst();
 
 		if ($template === NULL) {
-			$template = $this->templateRepository->findOneByTemplate(
-				$this->extensionKey, $this->templateName, 'default', $siteRootId
-			);
+			$site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($this->pid);
+			$fallbackLanguages = [];
+			foreach ($this->siteLanguage->getFallbackLanguageIds() as $fallbackLanguageId) {
+				$fallbackLanguages[] = $site->getLanguageById($fallbackLanguageId);
+			}
+
+			$template = $this->getTemplateRepository()->findByTemplateProperties(
+				$this->extensionKey, $this->templateName, $fallbackLanguages, $this->pid
+			)->getFirst();
 		}
+
 		self::$templateObjectCache[$templateHash] = $template;
 		return $template;
 	}
@@ -656,14 +463,15 @@ class MailTemplateService {
 	/**
 	 * Get the hash for the object cache
 	 *
-	 * @param $extensionKey
-	 * @param $templateName
-	 * @param $siteRootId
-	 * @param $languageId
 	 * @return string
 	 */
-	private function getTemplateHash($extensionKey, $templateName, $siteRootId, $languageId) {
-		return md5($extensionKey . '_' . $templateName . '_' . $siteRootId . '_' . $languageId);
+	private function getTemplateHash(): string {
+		return md5(
+			$this->extensionKey . '_' .
+			$this->templateName . '_' .
+			$this->pid . '_' .
+			$this->siteLanguage->getLanguageId()
+		);
 	}
 
 	/**
@@ -671,16 +479,21 @@ class MailTemplateService {
 	 *
 	 * @param Template $template
 	 */
-	private function loadTemplateValues(Template $template) {
-		$fromName = \trim($template->getFromName());
+	private function loadTemplateValues(Template $template): void {
+		$this->resetTemplate();
+		$this->extensionKey = $template->getExtensionKey();
+		$this->templateName = $template->getTemplateName();
+
+		$fromName = trim($template->getFromName());
 		if ($fromName === '') {
 			$fromName = $this->fromName;
 		}
+
 		if ($fromName === '' && $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']) {
 			$fromName = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName'];
 		}
 
-		$fromMail = $this->getValidFromMail(\trim($template->getFromMail()));
+		$fromMail = $this->getValidFromMail(trim($template->getFromMail()));
 		// The setters check if the value is empty or not
 		$this->setFromAddress($fromMail, $fromName);
 		$this->setCcAddresses($template->getCc());
@@ -696,14 +509,15 @@ class MailTemplateService {
 	 * @param string $fromMail
 	 * @return string
 	 */
-	private function getValidFromMail($fromMail): string {
-		$fromMail = \trim($fromMail);
-		if (!\filter_var($fromMail, FILTER_VALIDATE_EMAIL)) {
+	private function getValidFromMail(string $fromMail): string {
+		$fromMail = trim($fromMail);
+		if (!filter_var($fromMail, FILTER_VALIDATE_EMAIL)) {
 			$fromMail = $this->fromAddress;
 		}
-		if (!\filter_var($fromMail, FILTER_VALIDATE_EMAIL)) {
+
+		if (!filter_var($fromMail, FILTER_VALIDATE_EMAIL)) {
 			$fromMail = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'];
-			if (!\filter_var($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'], FILTER_VALIDATE_EMAIL)) {
+			if (!filter_var($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'], FILTER_VALIDATE_EMAIL)) {
 				$fromMail = 'noreply@example.com';
 			}
 		}
@@ -711,74 +525,17 @@ class MailTemplateService {
 		return $fromMail;
 	}
 
-	/**
-	 * @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 $bccAddresses
-	 * @return MailTemplateService
-	 */
-	public function setBccAddresses($bccAddresses): MailTemplateService {
-		if ($bccAddresses) {
-			$this->bccAddresses = $bccAddresses;
-			$this->mailMessage->setBcc(GeneralUtility::trimExplode(',', $this->bccAddresses));
-		}
-
-		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 $fromName
-	 */
-	public function setFromName($fromName) {
-		$this->fromName = $fromName;
-	}
 
 	/**
 	 * Get the default content for this template
 	 *
 	 * @param Template|null $template
-	 * @return bool|false|string
-	 * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
+	 * @return bool|string
+	 * @throws Exception
+	 * @throws NoSuchCacheException
 	 */
-	protected function getDefaultTemplateContent($template) {
+	protected function getDefaultTemplateContent(Template $template = NULL) {
 		$defaultTemplateContent =
 			$this->registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['templateContent'];
 
@@ -789,8 +546,8 @@ class MailTemplateService {
 
 			// only standard template file is considered since version 4.1
 			$defaultTemplateFile = $templatePath . 'template.html';
-			if (\file_exists($defaultTemplateFile)) {
-				$defaultTemplateContent = \file_get_contents($defaultTemplateFile);
+			if (file_exists($defaultTemplateFile)) {
+				$defaultTemplateContent = file_get_contents($defaultTemplateFile);
 			} else {
 				// use configured default html template
 				if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
@@ -805,13 +562,14 @@ class MailTemplateService {
 					$tsSettings['mail']['defaultHtmlTemplate']
 				);
 
-				if (\file_exists($defaultTemplateFile)) {
-					$defaultTemplateContent = \file_get_contents($defaultTemplateFile);
+				if (file_exists($defaultTemplateFile)) {
+					$defaultTemplateContent = file_get_contents($defaultTemplateFile);
 				} else {
 					return FALSE;
 				}
 			}
 		}
+
 		return $defaultTemplateContent;
 	}
 
@@ -819,15 +577,9 @@ class MailTemplateService {
 	 * @param string $toAddresses
 	 * @return MailTemplateService
 	 */
-	public function setToAddresses($toAddresses): MailTemplateService {
+	public function setToAddresses(string $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;
 	}
 
@@ -836,14 +588,12 @@ class MailTemplateService {
 	 *
 	 * @param Template|null $template
 	 * @param string $defaultTemplateContent
-	 * @param int $siteRootId
-	 * @param boolean $isNewsletter
-	 * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
+	 * @throws Exception
+	 * @throws NoSuchCacheException
 	 */
 	protected function parseValuesForMail(
-		$template, $defaultTemplateContent,
-		$siteRootId
-	) {
+		Template $template = NULL, string $defaultTemplateContent = ''
+	): void {
 		if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
 			/** @var StandaloneView $emailView */
 			$emailView = $this->objectManager->get(StandaloneView::class);
@@ -868,18 +618,18 @@ class MailTemplateService {
 				trim(empty($overwrittenSubject) ? $template->getSubject() : $overwrittenSubject),
 				$emailView
 			);
-
 			$layoutId = $template->getLayout();
 			$templateContent = $template->getContent();
 			$this->setSubjectToSend($subject);
 		} else {
 			$subject = $this->registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['subject'];
-			if (\is_array($subject)) {
-				$subject = \trim(
+			if (is_array($subject)) {
+				$subject = trim(
 					$this->registerService->getRegisterArray()
-					[$this->extensionKey][$this->templateName]['subject'][$this->language]
+					[$this->extensionKey][$this->templateName]['subject'][$this->siteLanguage->getTypo3Language()]
 				);
 			}
+
 			$subject = $this->parseMarkers(
 				(empty($overwrittenSubject) ? $subject : $overwrittenSubject),
 				$emailView
@@ -890,7 +640,6 @@ class MailTemplateService {
 		}
 
 		$this->setSubjectToSend($subject);
-		$this->mailMessage->setSubject($subject);
 
 		// Parse the markers
 		if ($this->fromName) {
@@ -924,15 +673,20 @@ 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);
+		$emailBody = nl2br($emailBody);
+		$emailBody = preg_replace('/(<br[\s]?[\/]?>[\s]*){3,}/', '<br><br>', $emailBody);
 
-		$layout = $this->getLayoutSource($layoutId, $siteRootId);
+		$layout = $this->getLayoutRepository()->findByUidOrDefault(
+			$layoutId,
+			$this->pid,
+			$this->siteLanguage->getLanguageId()
+		);
 		$emailHTMLHead = '';
 		if ($layout) {
 			$emailHTMLHead = $layout->getHeadContent();
-			$emailBody = \str_replace('###CONTENT###', $emailBody, $layout->getContent());
+			$emailBody = str_replace('###CONTENT###', $emailBody, $layout->getContent());
 		}
+
 		$this->mailBodyToSend = '<html><head>' . $emailHTMLHead . '</head><body>' . $emailBody . '</body></html>';
 	}
 
@@ -944,23 +698,22 @@ class MailTemplateService {
 	 */
 	private function getAllMarker(array $markers): string {
 		$allMarker = '';
-
 		foreach ($markers as $key => $value) {
-			if (\array_key_exists($key, $this->markerLabels) && $this->markerLabels[$key] !== NULL) {
+			if (array_key_exists($key, $this->markerLabels) && $this->markerLabels[$key] !== NULL) {
 				$key = $this->markerLabels[$key];
 			}
 
-			if (\is_string($value)) {
+			if (is_string($value)) {
 				$allMarker .= $key . ': ' . $value . PHP_EOL;
-			} elseif (\is_array($value)) {
+			} elseif (is_array($value)) {
 				foreach ($value as $innerKey => $innerValue) {
 					$allMarker .= $key . '.' . $innerKey . ': ' . $innerValue . PHP_EOL;
 				}
-			} elseif (\is_bool($value)) {
+			} elseif (is_bool($value)) {
 				$valueAsString = $value ? 'true' : 'false';
 				$allMarker .= $key . ': ' . $valueAsString . PHP_EOL;
-			} elseif (\is_object($value)) {
-				if (\method_exists($value, '__toString')) {
+			} elseif (is_object($value)) {
+				if (method_exists($value, '__toString')) {
 					$allMarker .= $key . ': ' . $value->__toString() . PHP_EOL;
 				}
 			}
@@ -978,57 +731,39 @@ class MailTemplateService {
 	private function getAllMarkerHTML(array $markers): string {
 		$allMarker = '<table>';
 		$allMarker .= '<style> table { text-align: left; } table tr th, table tr td { border-bottom: 1px solid rgba(0,0,0,0.2); padding: 2px 6px 4px;} </style>';
-
 		foreach ($markers as $key => $value) {
-			if (\array_key_exists($key, $this->markerLabels) && $this->markerLabels[$key] !== NULL) {
+			if (array_key_exists($key, $this->markerLabels) && $this->markerLabels[$key] !== NULL) {
 				$key = $this->markerLabels[$key];
 			}
 
-			if (\is_string($value)) {
+			if (is_string($value)) {
 				$allMarker .= '<tr><th>' . $key . ' </th><td> ' . $value . '</td></tr>';
-			} elseif (\is_array($value)) {
+			} elseif (is_array($value)) {
 				foreach ($value as $innerKey => $innerValue) {
 					$allMarker .= '<tr><th>' . $key . '.' . $innerKey . ' </th><td> ' . $innerValue . '</td></tr>';
 				}
-			} elseif (\is_bool($value)) {
+			} elseif (is_bool($value)) {
 				$valueAsString = $value ? 'true' : 'false';
 				$allMarker .= '<tr><th>' . $key . ' </th><td> ' . $valueAsString . '</td></tr>';
-			} elseif (\is_object($value)) {
-				if (\method_exists($value, '__toString')) {
+			} elseif (is_object($value)) {
+				if (method_exists($value, '__toString')) {
 					$allMarker .= '<tr><th>' . $key . ' </th><td> ' . $value->__toString() . '</td></tr>';
 				}
 			}
 		}
 
-		$allMarker .= '</table>';
-
-		return $allMarker;
+		return $allMarker . '</table>';
 	}
 
 	/**
+	 * Parses markers in an email View.
+	 * !!! CHANGES THE SOURCE PATH AND IT SHOULD BE RESET BACK TO THE ORIGINAL!!!
+	 *
+	 * @param string $text
+	 * @param StandaloneView $emailView
 	 * @return string
 	 */
-	public function getOverwrittenEmailBody(): string {
-		return $this->overwrittenEmailBody;
-	}
-
-	/**
-	 * @param string $overwrittenEmailBody
-	 */
-	public function setOverwrittenEmailBody(string $overwrittenEmailBody) {
-		$this->overwrittenEmailBody = $overwrittenEmailBody;
-	}
-
-	/**
-	 * Parses markers in an email View.
-	 * !!! CHANGES THE SOURCE PATH AND IT SHOULD BE RESET BACK TO THE ORIGINAL!!!
-	 *
-	 * @param string $text
-	 * @param StandaloneView $emailView
-	 * @return mixed
-	 */
-	protected function parseMarkers($text, $emailView) {
-		$text = (string) $text;
+	protected function parseMarkers(string $text, StandaloneView $emailView): string {
 		if (strpos($text, '{') !== FALSE) {
 			$emailView->setTemplateSource($text);
 			return $emailView->render();
@@ -1037,107 +772,100 @@ class MailTemplateService {
 		return $text;
 	}
 
-	/**
-	 * Returns the layout.
-	 *
-	 * @param int $layoutUid
-	 * @param int $siteRootId
-	 * @return Layout|NULL
-	 */
-	private function getLayoutSource(int $layoutUid, int $siteRootId) {
-		$languageUid = 0;
-		if ($this->language !== self::DEFAULT_LANGUAGE) {
-			$languageUid = (int) array_search($this->language, $this->getAvailableLanguages(), TRUE);
-		}
-
-		return $this->layoutRepository->findByUidOrDefault($layoutUid, $siteRootId, $languageUid);
-	}
-
-	/**
-	 * Returns the list of available translation languages
-	 *
-	 * @return array
-	 */
-	private function getAvailableLanguages(): array {
-		$out = [0 => ''];
-		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
-	 * @param string $subject
-	 * @param string $emailBody
-	 * @param int $sendingTime
-	 * @param int $priority
-	 * @param int $lastSendingTime
-	 * @param string $language
-	 * @param int $pid
 	 * @return Mail
-	 * @throws \InvalidArgumentException
-	 * @throws \BadFunctionCallException
-	 * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
-	 * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
-	 */
-	private function addMailToMailQueue(
-		$extensionKey, $templateName, $subject, $emailBody, $priority, $sendingTime = 0,
-		$lastSendingTime = 0, $language = self::DEFAULT_LANGUAGE, $pid = 0
-	): Mail {
-		$mail = new Mail();
-		$mail->setPid($pid);
-		$mail->setExtensionKey($extensionKey);
-		$mail->setTemplateName($templateName);
-		$mail->setLanguage($language);
-		$mail->setBlacklisted($this->registerService->isTemplateBlacklisted($extensionKey, $templateName, $pid));
-
+	 * @throws Exception
+	 * @throws IllegalObjectTypeException
+	 * @throws NoSuchCacheException
+	 */
+	private function addMailToMailQueue(): Mail {
+		$mail = GeneralUtility::makeInstance(Mail::class);
+		$mail->setPid($this->pid);
+		$mail->setExtensionKey($this->extensionKey);
+		$mail->setTemplateName($this->templateName);
+		$mail->setLanguage(explode('.', $this->siteLanguage->getLocale())[0]);
+		$mail->setBlacklisted(
+			$this->registerService->isTemplateBlacklisted(
+				$this->extensionKey,
+				$this->templateName,
+				$this->pid
+			)
+		);
 		$mail->setFromAddress($this->fromAddress);
 		$mail->setFromName($this->fromName);
-
 		$mail->setToAddress($this->toAddresses);
-		$mail->setMailSubject($subject);
-		$mail->setMailBody($emailBody);
-		$mail->setPriority($priority);
+		$mail->setMailSubject($this->getSubjectToSend());
+		$mail->setMailBody($this->getMailBodyToSend());
+		$mail->setPriority($this->priority);
 		$mail->setBccAddresses($this->bccAddresses);
 		$mail->setCcAddresses($this->ccAddresses);
-		$mail->setSendingTime($sendingTime);
-		$mail->setLastSendingTime($lastSendingTime);
+		$mail->setSendingTime(0);
+		$mail->setLastSendingTime(0);
 		$mail->setReplyTo($this->replyToAddress);
 		foreach ($this->markers as $marker) {
 			if ($marker instanceof FileReference) {
 				// we need to create proper copies of the attachment so that the original file reference does not get
 				// moved over to the mail model and worst case, the original model loses the reference because of this
 				$originalResource = $marker->getOriginalResource();
-				if ($originalResource instanceof \TYPO3\CMS\Core\Resource\FileReference) {
-					$coreFileReferenceMailFile = $this->resourceFactory->createFileReferenceObject(
+				if ($originalResource instanceof CoreFileReference) {
+					$coreFileReferenceMailFile = GeneralUtility::makeInstance(ResourceFactory::class)
+						->createFileReferenceObject(
 						[
 							'uid_local' => $originalResource->getOriginalFile()->getUid(),
 							'table_local' => 'sys_file',
 							'uid' => uniqid('NEW_MAIL', TRUE)
 						]
 					);
-					$newFileReference = new FileReference();
+					$newFileReference = GeneralUtility::makeInstance(FileReference::class);
 					$newFileReference->setOriginalResource($coreFileReferenceMailFile);
 					$mail->addAttachment($newFileReference);
 				}
 			}
 		}
 
+		$mailRepository = $this->getMailRepository();
+		$mailRepository->add($mail);
+		$mailRepository->persist();
+		return $mail;
+	}
+
+	/**
+	 * Send a Mail from the queue, identified by its id
+	 *
+	 * @param int $uid
+	 * @return bool
+	 * @throws Exception
+	 */
+	public function sendMailFromQueue(int $uid): bool {
+		if (!isset(self::$mailObjectCache[$uid]) || !self::$mailObjectCache[$uid] instanceof Mail) {
+			$mailToSend = $this->getMailObjectByUid($uid);
+			if ($mailToSend === FALSE) {
+				return FALSE;
+			}
+		} else {
+			$mailToSend = self::$mailObjectCache[$uid];
+		}
+
+		$this->sendMailsFromQueue([$mailToSend]);
+		$success = FALSE;
+		if ($mailToSend->getStatus() === Mail::STATUS_SENT) {
+			$success = TRUE;
+		}
+
+		unset(self::$mailObjectCache[$uid]); // free the memory
+		return $success;
+	}
+
+	/**
+	 * Get the mail object by uid and check if it's blacklisted
+	 *
+	 * @param int $uid
+	 * @return bool|object
+	 * @throws Exception
+	 */
+	protected function getMailObjectByUid(int $uid): ?Mail {
 		if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
 			/** @var MailRepository $mailRepository */
 			$mailRepository = $this->objectManager->get(MailRepository::class);
@@ -1145,155 +873,375 @@ class MailTemplateService {
 			$mailRepository = GeneralUtility::makeInstance(MailRepository::class);
 		}
 
-		$mailRepository->add($mail);
-		$mailRepository->persist();
-		return $mail;
+		$mailObject = $mailRepository->findOneByUid($uid);
+		if (!$mailObject || $mailObject->getBlacklisted()) {
+			return NULL;
+		}
+
+		return $mailObject;
 	}
 
 	/**
-	 * @return string
+	 * Add html and plain body text to the mail message object
+	 *
+	 * @param MailMessage $mailMessage
+	 * @param string $htmlBody
+	 * @param string $plainBody
 	 */
-	public function getSubjectToSend(): string {
-		return $this->subjectToSend;
+	protected static function addBodyToMailMessage(MailMessage $mailMessage, string $htmlBody = '', string $plainBody = ''): void {
+		if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
+			$mailMessage->setBody($htmlBody, 'text/html');
+			$mailMessage->addPart($plainBody, 'text/plain');
+		} else {
+			$mailMessage->html($htmlBody);
+			$mailMessage->text($plainBody);
+		}
 	}
 
 	/**
-	 * @param string $subjectToSend
+	 * Attach a file
+	 * @param MailMessage $mailMessage
+	 * @param FileInterface $file
 	 */
-	public function setSubjectToSend(string $subjectToSend) {
-		$this->subjectToSend = $subjectToSend;
+	protected static function attachToMailMessage(MailMessage $mailMessage, FileInterface $file): void {
+		if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
+			$mailMessage->attach(
+				Swift_Attachment::newInstance($file->getContents(), $file->getName(), $file->getMimeType())
+			);
+		} else {
+			$mailMessage->attach(
+				$file->getContents(), $file->getName(), $file->getMimeType()
+			);
+		}
 	}
 
 	/**
-	 * @return string|string[]|null
+	 *
+	 * @param Mail[] $mails
+	 * @throws Exception
+	 * @throws IllegalObjectTypeException
+	 * @throws UnknownObjectException
+	 */
+	public function sendMailsFromQueue(array $mails): void {
+		foreach ($mails as $mail) {
+			$mailMessage = GeneralUtility::makeInstance(MailMessage::class);
+			$toAddresses = trim($mail->getToAddress());
+			$addressesArray = GeneralUtility::trimExplode(',', $mail->getToAddress(), TRUE);
+			if (count($addressesArray) > 1) {
+				$toAddresses = $addressesArray;
+			}
+
+			$mailMessage->setTo($toAddresses);
+			$mailMessage->setFrom($mail->getFromAddress(), $mail->getFromName());
+			$mailMessage->setCc(
+				GeneralUtility::trimExplode(',', $mail->getCcAddresses(), TRUE)
+			);
+			$mailMessage->setBcc(
+				GeneralUtility::trimExplode(',', $mail->getBccAddresses(), TRUE)
+			);
+			$mailMessage->setSubject($mail->getMailSubject());
+			$plaintextService = GeneralUtility::makeInstance(PlaintextService::class);
+			$plaintextBody = $plaintextService->makePlain($mail->getMailBody());
+			self::addBodyToMailMessage($mailMessage, $mail->getMailBody(), $plaintextBody);
+
+			if ($mail->getBccAddresses()) {
+				$mailMessage->setBcc(GeneralUtility::trimExplode(',', $mail->getBccAddresses()));
+			}
+
+			if ($mail->getCcAddresses()) {
+				$mailMessage->setCc(GeneralUtility::trimExplode(',', $mail->getCcAddresses()));
+			}
+
+			if ($mail->getReplyTo()) {
+				$mailMessage->setReplyTo($mail->getReplyTo());
+			}
+
+			$attachments = $mail->getAttachments();
+			if ($attachments->count() > 0) {
+				foreach ($attachments as $attachment) {
+					/**
+					 * @var FileReference $attachment
+					 */
+					$originalResource = $attachment->getOriginalResource();
+					if ($originalResource === NULL) {
+						continue;
+					}
+
+					$file = $originalResource->getOriginalFile();
+					self::attachToMailMessage($mailMessage, $file);
+				}
+			}
+
+			$dateTime = new DateTime();
+			if ($mail->getSendingTime() === 0) {
+				$mail->setSendingTime($dateTime->getTimestamp());
+			}
+
+			$mail->setLastSendingTime($dateTime->getTimestamp());
+			try {
+				$success = $mailMessage->send();
+				if (!$success) {
+					$mail->setStatus(Mail::STATUS_ERROR);
+					$mail->setErrorMessage(LocalizationUtility::translate('backend.success_mail_queue', 'sg_mail'));
+				}
+				$mail->setStatus(Mail::STATUS_SENT);
+			} catch (TransportException $exception) {
+				$mail->setStatus(Mail::STATUS_ERROR);
+				$mail->setErrorMessage($exception->getMessage());
+			}
+
+			$this->getMailRepository()->update($mail);
+		}
+
+		$this->getMailRepository()->persist();
+	}
+
+	/**
+	 * @param SiteLanguage $siteLanguage
+	 * @return $this
 	 */
-	public function getMailBodyToSend() {
-		return $this->mailBodyToSend;
+	public function setSiteLanguage(SiteLanguage $siteLanguage): MailTemplateService {
+		$this->siteLanguage = $siteLanguage;
+		return $this;
+	}
+
+	/**
+	 * @param string $templateName
+	 * @return MailTemplateService
+	 */
+	public function setTemplateName(string $templateName): MailTemplateService {
+		$this->templateName = $templateName;
+		return $this;
 	}
 
 	/**
-	 * @param string|string[]|null $mailBodyToSend
+	 * @param string $extensionKey
+	 * @return MailTemplateService
 	 */
-	public function setMailBodyToSend($mailBodyToSend) {
-		$this->mailBodyToSend = $mailBodyToSend;
+	public function setExtensionKey(string $extensionKey): MailTemplateService {
+		$this->extensionKey = $extensionKey;
+		return $this;
 	}
 
 	/**
-	 * Send a Mail from the queue, identified by its id
-	 *
-	 * @param int $uid
-	 * @return bool|NULL
-	 * @throws \TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException
-	 * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
-	 * @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
+	 * @param array $markers
+	 * @return MailTemplateService
 	 */
-	public function sendMailFromQueue($uid): bool {
-		if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
-			/** @var MailRepository $mailRepository */
-			$mailRepository = $this->objectManager->get(MailRepository::class);
-		} else {
-			$mailRepository = GeneralUtility::makeInstance(MailRepository::class);
-		}
+	public function addMarkers(array $markers): MailTemplateService {
+		$this->setMarkers(array_merge($this->markers, $markers));
+		return $this;
+	}
 
-		/** @var Mail $mailToSend */
-		if (!isset(self::$mailObjectCache[$uid]) || !self::$mailObjectCache[$uid] instanceof Mail) {
-			$mailToSend = $this->getMailObjectByUid($uid);
-			if ($mailToSend === FALSE) {
-				return FALSE;
+	/**
+	 * @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;
 			}
-		} else {
-			$mailToSend = self::$mailObjectCache[$uid];
+			$this->markerLabels[$key] = $currentMarker['markerLabel'];
 		}
 
-		$plaintextService = GeneralUtility::makeInstance(PlaintextService::class);
-		$plaintextBody = $plaintextService->makePlain($mailToSend->getMailBody());
-		if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
-			$this->mailMessage->setBody($mailToSend->getMailBody(), 'text/html');
-			$this->mailMessage->addPart($plaintextBody, 'text/plain');
-		} else {
-			$this->mailMessage->html($mailToSend->getMailBody());
-			$this->mailMessage->text($plaintextBody);
-		}
+		return $this;
+	}
 
-		$toAddresses = \trim($mailToSend->getToAddress());
-		$addressesArray = GeneralUtility::trimExplode(',', $toAddresses, TRUE);
-		if (\count($addressesArray) > 1) {
-			$toAddresses = $addressesArray;
-		}
+	/**
+	 * @param int $priority
+	 * @return MailTemplateService
+	 */
+	public function setPriority(int $priority): MailTemplateService {
+		$this->priority = $priority;
+		return $this;
+	}
 
-		$this->mailMessage->setTo($toAddresses);
-		$this->mailMessage->setFrom($mailToSend->getFromAddress(), $mailToSend->getFromName());
-		$this->mailMessage->setSubject($mailToSend->getMailSubject());
-		if ($mailToSend->getBccAddresses()) {
-			$this->mailMessage->setBcc(GeneralUtility::trimExplode(',', $mailToSend->getBccAddresses()));
+	/**
+	 * @param string $fromAddress
+	 * @param string $fromName
+	 * @return MailTemplateService
+	 */
+	public function setFromAddress(string $fromAddress, string $fromName = ''): MailTemplateService {
+		if ($fromAddress) {
+			$this->fromAddress = $fromAddress;
 		}
 
-		if ($mailToSend->getCcAddresses()) {
-			$this->mailMessage->setCc(GeneralUtility::trimExplode(',', $mailToSend->getCcAddresses()));
-		}
+		return $this;
+	}
 
-		if ($mailToSend->getReplyTo()) {
-			$this->mailMessage->setReplyTo($mailToSend->getReplyTo());
+	/**
+	 * @param string $ccAddresses
+	 * @return MailTemplateService
+	 */
+	public function setCcAddresses(string $ccAddresses): MailTemplateService {
+		if ($ccAddresses) {
+			$this->ccAddresses = $ccAddresses;
 		}
 
-		$attachments = $mailToSend->getAttachments();
-		if ($attachments->count() > 0) {
-			foreach ($attachments as $attachment) {
-				/**
-				 * @var FileReference $attachment
-				 */
-				$file = $attachment->getOriginalResource()->getOriginalFile();
-				if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
-					$this->mailMessage->attach(
-						\Swift_Attachment::newInstance($file->getContents(), $file->getName(), $file->getMimeType())
-					);
-				} else {
-					$this->mailMessage->attach(
-						$file->getContents(), $file->getName(), $file->getMimeType()
-					);
-				}
-			}
-		}
+		return $this;
+	}
 
-		$dateTime = new DateTime();
-		if ($mailToSend->getSendingTime() === 0) {
-			$mailToSend->setSendingTime($dateTime->getTimestamp());
+	/**
+	 * @param string $bccAddresses
+	 * @return MailTemplateService
+	 */
+	public function setBccAddresses(string $bccAddresses): MailTemplateService {
+		if ($bccAddresses) {
+			$this->bccAddresses = $bccAddresses;
 		}
 
-		$mailToSend->setLastSendingTime($dateTime->getTimestamp());
-		try {
-			$success = $this->mailMessage->send();
-		} catch (TransportException $exception) {
-			$success = FALSE;
-		}
+		return $this;
+	}
 
-		if ($success) {
-			$mailRepository->update($mailToSend);
-			$mailRepository->persist();
+	/**
+	 * @param string $replyToAddress
+	 * @return MailTemplateService
+	 */
+	public function setReplyToAddress(string $replyToAddress): MailTemplateService {
+		if ($replyToAddress) {
+			$this->replyToAddress = $replyToAddress;
 		}
 
-		unset(self::$mailObjectCache[$uid]); // free the memory
-		return $success;
+		return $this;
 	}
 
 	/**
-	 * Get the mail object by uid and check if it's blacklisted
+	 * @param string $fromName
+	 * @return MailTemplateService
+	 */
+	public function setFromName(string $fromName): MailTemplateService {
+		$this->fromName = $fromName;
+		return $this;
+	}
+
+	/**
+	 * @param bool $ignoreMailQueue
+	 * @return MailTemplateService
+	 */
+	public function setIgnoreMailQueue(bool $ignoreMailQueue): MailTemplateService {
+		$this->ignoreMailQueue = $ignoreMailQueue;
+		return $this;
+	}
+
+	/**
+	 * @return string
+	 */
+	public function getSubjectToSend(): string {
+		return $this->subjectToSend;
+	}
+
+	/**
+	 * @param string $subjectToSend
+	 * @return MailTemplateService
+	 */
+	public function setSubjectToSend(string $subjectToSend): MailTemplateService {
+		$this->subjectToSend = $subjectToSend;
+		return $this;
+	}
+
+	/**
+	 * @return string
+	 */
+	public function getMailBodyToSend(): string {
+		return $this->mailBodyToSend;
+	}
+
+	/**
+	 * @param string $mailBodyToSend
+	 * @return MailTemplateService
+	 */
+	public function setMailBodyToSend(string $mailBodyToSend): MailTemplateService {
+		$this->mailBodyToSend = $mailBodyToSend;
+		return $this;
+	}
+
+	/**
+	 * @return string
+	 */
+	public function getOverwrittenEmailBody(): string {
+		return $this->overwrittenEmailBody;
+	}
+
+	/**
+	 * @param string $overwrittenEmailBody
+	 * @return MailTemplateService
+	 */
+	public function setOverwrittenEmailBody(string $overwrittenEmailBody): MailTemplateService {
+		$this->overwrittenEmailBody = $overwrittenEmailBody;
+		return $this;
+	}
+
+	/**
+	 * set the page id from which this was called
 	 *
-	 * @param int $uid
-	 * @return bool|object
+	 * @param int $pid
+	 * @return MailTemplateService
 	 */
-	public function getMailObjectByUid($uid) {
-		if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) {
-			/** @var MailRepository $mailRepository */
-			$mailRepository = $this->objectManager->get(MailRepository::class);
-		} else {
-			$mailRepository = GeneralUtility::makeInstance(MailRepository::class);
+	public function setPid(int $pid): MailTemplateService {
+		$this->pid = $pid;
+		return $this;
+	}
+
+	/**
+	 * @return string
+	 */
+	public function getSubject(): string {
+		return $this->subject;
+	}
+
+	/**
+	 * @param string $subject
+	 */
+	public function setSubject(string $subject): void {
+		$this->subject = $subject;
+	}
+
+	/**
+	 * @return LayoutRepository
+	 * @throws Exception
+	 */
+	protected function getLayoutRepository(): LayoutRepository {
+		if ($this->layoutRepository === NULL) {
+			if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0')) {
+				$this->layoutRepository = $this->objectManager->get(LayoutRepository::class);
+			} else {
+				$this->layoutRepository = GeneralUtility::makeInstance(LayoutRepository::class);
+			}
 		}
 
-		$mailObject = $mailRepository->findOneByUid($uid);
-		if (!$mailObject || $mailObject->getBlacklisted()) {
-			return FALSE;
+		return $this->layoutRepository;
+	}
+
+	/**
+	 * @return TemplateRepository
+	 * @throws Exception
+	 */
+	protected function getTemplateRepository(): TemplateRepository {
+		if ($this->templateRepository === NULL) {
+			if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0')) {
+				$this->templateRepository = $this->objectManager->get(TemplateRepository::class);
+			} else {
+				$this->templateRepository = GeneralUtility::makeInstance(TemplateRepository::class);
+			}
 		}
-		return $mailObject;
+
+		return $this->templateRepository;
+	}
+
+	/**
+	 * @return MailRepository
+	 * @throws Exception
+	 */
+	protected function getMailRepository(): MailRepository {
+		if ($this->mailRepository === NULL) {
+			if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0')) {
+				$this->mailRepository = $this->objectManager->get(MailRepository::class);
+			} else {
+				$this->mailRepository = GeneralUtility::makeInstance(MailRepository::class);
+			}
+		}
+
+		return $this->mailRepository;
 	}
 }
diff --git a/Classes/Updates/LanguageMigrationUpdate.php b/Classes/Updates/LanguageMigrationUpdate.php
new file mode 100644
index 0000000000000000000000000000000000000000..c9e23fb63f0d748609f41da8714d7c8c23ef83f8
--- /dev/null
+++ b/Classes/Updates/LanguageMigrationUpdate.php
@@ -0,0 +1,101 @@
+<?php
+/*******************************************************************************
+ * 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!
+ ******************************************************************************/
+
+namespace SGalinski\SgMail\Updates;
+
+use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Site\SiteFinder;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
+use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
+
+class LanguageMigrationUpdate implements UpgradeWizardInterface {
+	public const IDENTIFIER = 'sgmail_languagemigrationupdate';
+
+	/**
+	 * @return string
+	 */
+	public function getIdentifier(): string {
+		return self::IDENTIFIER;
+	}
+
+	/**
+	 * @return string
+	 */
+	public function getTitle(): string {
+		return 'Language migration wizard';
+	}
+
+	/**
+	 * @return string
+	 */
+	public function getDescription(): string {
+		return 'This wizard migrates the language values of mails and templates to more reasonable values then two letter isocodes';
+	}
+
+	/**
+	 * @return bool
+	 */
+	public function executeUpdate(): bool {
+		$sites = GeneralUtility::makeInstance(SiteFinder::class)->getAllSites();
+		$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
+		foreach ($sites as $site) {
+			$languages = $site->getAllLanguages();
+			foreach ($languages as $language) {
+				$queryBuilder = $connectionPool->getQueryBuilderForTable('tx_sgmail_domain_model_mail');
+				$queryBuilder->update('tx_sgmask_domain_model_mail')
+					->set('language', explode('.', $language->getLocale()))
+					->where(
+						$queryBuilder->expr()->like('language', $language->getTypo3Language())
+					)->execute();
+
+				$queryBuilder = $connectionPool->getQueryBuilderForTable('tx_sgmail_domain_model_template');
+				$queryBuilder->update('tx_sgmail_domain_model_template')
+					->set('sys_language_uid', $language->getLanguageId())
+					->where(
+						$queryBuilder->expr()->like('language', $language->getTypo3Language())
+					)->execute();
+			}
+		}
+
+		return TRUE;
+	}
+
+	/**
+	 * @return bool
+	 */
+	public function updateNecessary(): bool {
+		return TRUE;
+	}
+
+	/**
+	 * @return string[]
+	 */
+	public function getPrerequisites(): array {
+		return [
+			DatabaseUpdatedPrerequisite::class
+		];
+	}
+}
diff --git a/Classes/Updates/SendStatusUpdate.php b/Classes/Updates/SendStatusUpdate.php
new file mode 100644
index 0000000000000000000000000000000000000000..44034c6893add982bc088657e90b5a57440d879a
--- /dev/null
+++ b/Classes/Updates/SendStatusUpdate.php
@@ -0,0 +1,99 @@
+<?php
+/*******************************************************************************
+ * 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!
+ ******************************************************************************/
+
+namespace SGalinski\SgMail\Updates;
+
+use SGalinski\SgMail\Domain\Model\Mail;
+use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
+use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
+
+/**
+ * Class SendStatusUpdate
+ *
+ * @package SGalinski\SgMail\Updates
+ */
+class SendStatusUpdate implements UpgradeWizardInterface {
+	public const IDENTIFIER = 'sgmail_sendstatusupdate';
+
+	/**
+	 * @inheritDoc
+	 */
+	public function getIdentifier(): string {
+		return self::IDENTIFIER;
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	public function getTitle(): string {
+		return 'Update the send status of mails';
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	public function getDescription(): string {
+		return 'This wizard updates the status of mails that have a sending_time set to sent appropriately.';
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	public function executeUpdate(): bool {
+		$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_sgmail_domain_model_mail');
+		$queryBuilder->update('tx_sgmail_domain_model_mail')
+			->set('status', Mail::STATUS_SENT)
+			->where(
+				$queryBuilder->expr()->gt('sending_time', 0),
+				$queryBuilder->expr()->eq('status', Mail::STATUS_PENDING)
+			)->execute();
+		return TRUE;
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	public function updateNecessary(): bool {
+		$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_sgmail_domain_model_mail');
+		$count = $queryBuilder->count('*')
+			->from('tx_sgmail_domain_model_mail')
+			->where(
+				$queryBuilder->expr()->gt('sending_time', 0),
+				$queryBuilder->expr()->eq('status', Mail::STATUS_PENDING)
+			)->execute()->fetchOne();
+		return $count > 0;
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	public function getPrerequisites(): array {
+		return [
+			DatabaseUpdatedPrerequisite::class
+		];
+	}
+}
diff --git a/Classes/Updates/UpdateGermanAsDefault.php b/Classes/Updates/UpdateGermanAsDefault.php
deleted file mode 100644
index 1ef546aa4b92ff59b780cd35fa31c9bae903ecc2..0000000000000000000000000000000000000000
--- a/Classes/Updates/UpdateGermanAsDefault.php
+++ /dev/null
@@ -1,135 +0,0 @@
-<?php
-/***************************************************************
- *  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!
- ***************************************************************/
-
-namespace SGalinski\SgMail\Updates;
-
-use TYPO3\CMS\Core\Database\Connection;
-use TYPO3\CMS\Core\Database\ConnectionPool;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
-use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
-
-/**
- *    Makes german templates the default and former default as english templates
- */
-class UpdateGermanAsDefault implements UpgradeWizardInterface {
-	/**
-	 * The wizard identifier
-	 */
-	public const IDENTIFIER = 'tx_sgmail_update_german_as_default';
-
-	/**
-	 * @var string
-	 */
-	protected $table = 'tx_sgmail_domain_model_template';
-
-	/**
-	 * @return string
-	 */
-	public function getIdentifier(): string {
-		return self::IDENTIFIER;
-	}
-
-	/**
-	 * @return string
-	 */
-	public function getTitle(): string {
-		return 'Makes german templates the default and former default as english templates. WARNING: ONLY EXECUTE THIS IF IT MAKES SENSE FOR YOUR TYPO3 INSTANCE';
-	}
-
-	/**
-	 * @return string
-	 */
-	public function getDescription(): string {
-		return '';
-	}
-
-	/**
-	 * @return bool
-	 */
-	public function executeUpdate(): bool {
-		$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
-		$queryBuilder->getRestrictions()->removeAll();
-		$resultGerman = $queryBuilder->select('uid')
-			->from($this->table)
-			->where(
-				$queryBuilder->expr()->eq('language', $queryBuilder->createNamedParameter('de'))
-			)
-			->execute()->fetchAllAssociative();
-
-		$resultDefault = $queryBuilder->select('uid')
-			->from($this->table)
-			->where(
-				$queryBuilder->expr()->eq('language', $queryBuilder->createNamedParameter('default'))
-			)
-			->execute()->fetchAllAssociative();
-
-		/** @var array $resultGerman */
-		foreach ($resultGerman as $row) {
-			$queryBuilder->update($this->table)
-				->where(
-					$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($row[0], Connection::PARAM_INT))
-				)
-				->set('language', 'default', TRUE)
-				->execute();
-		}
-
-		/** @var array $resultGerman */
-		foreach ($resultDefault as $row) {
-			$queryBuilder->update($this->table)
-				->where(
-					$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($row[0], Connection::PARAM_INT))
-				)
-				->set('language', 'en', TRUE)
-				->execute();
-		}
-
-		return TRUE;
-	}
-
-	/**
-	 * @return bool
-	 */
-	public function updateNecessary(): bool {
-		$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
-		$queryBuilder->getRestrictions()->removeAll();
-		$rowCount = $queryBuilder->select('*')
-			->from($this->table)
-			->where(
-				$queryBuilder->expr()->eq('language', $queryBuilder->createNamedParameter('de'))
-			)
-			->execute()->rowCount();
-		return $rowCount > 0;
-	}
-
-	/**
-	 * @return array|string[]
-	 */
-	public function getPrerequisites(): array {
-		return [
-			DatabaseUpdatedPrerequisite::class
-		];
-	}
-}
diff --git a/Classes/Updates/UpdateLanguages.php b/Classes/Updates/UpdateLanguages.php
deleted file mode 100644
index 34a11e7ec470b7661cecdb6fadb47dbe21dc427a..0000000000000000000000000000000000000000
--- a/Classes/Updates/UpdateLanguages.php
+++ /dev/null
@@ -1,147 +0,0 @@
-<?php
-/***************************************************************
- *  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!
- ***************************************************************/
-
-namespace SGalinski\SgMail\Updates;
-
-use SGalinski\SgMail\Service\BackendService;
-use TYPO3\CMS\Core\Database\Connection;
-use TYPO3\CMS\Core\Database\ConnectionPool;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
-use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
-
-/**
- * Fix all incorrect / deprecated language codes (be languages instead of sys languages) in the database
- */
-class UpdateLanguages implements UpgradeWizardInterface {
-	/**
-	 * The wizard identifier
-	 */
-	public const IDENTIFIER = 'tx_sgmail_update_languages';
-
-	/**
-	 * @var array
-	 */
-	protected $tables = [
-		'tx_sgmail_domain_model_mail', 'tx_sgmail_domain_model_template'
-	];
-
-	/**
-	 * is used to map language codes. If empty the updatewizard will ignore this update
-	 * example: you want to change en-us to en
-	 * [
-	 *    'en-us' => 'en'
-	 * ]
-	 *
-	 * @var array
-	 */
-	protected $languageMap = [
-
-	];
-
-	/**
-	 * @return string
-	 */
-	public function getIdentifier(): string {
-		return self::IDENTIFIER;
-	}
-
-	/**
-	 * @return string
-	 */
-	public function getTitle(): string {
-		return 'Find all templates & queue entries with an incorrect (be languages instead of sys languages) language code and fix it';
-	}
-
-	/**
-	 * @return string
-	 */
-	public function getDescription(): string {
-		return '';
-	}
-
-	/**
-	 * @return bool
-	 */
-	public function executeUpdate(): bool {
-		foreach ($this->tables as $table) {
-			$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
-			$queryBuilder->getRestrictions()->removeAll();
-			foreach ($this->languageMap as $origin => $target) {
-				$queryBuilder->update($table)
-					->where(
-						$queryBuilder->expr()->eq('language', $queryBuilder->createNamedParameter($origin))
-					)
-					->set('language', $target, TRUE)
-					->execute();
-			}
-		}
-
-		return TRUE;
-	}
-
-	/**
-	 * @return bool
-	 */
-	public function updateNecessary(): bool {
-		$upgradeNecessary = FALSE;
-
-		if (count($this->languageMap) > 0) {
-			$languages = BackendService::getLanguages();
-
-			foreach ($this->tables as $table) {
-				$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
-				$queryBuilder->getRestrictions()->removeAll();
-				$rowCount = $queryBuilder->select('language')
-					->from($table)
-					->where(
-						$queryBuilder->expr()->notIn(
-							'language',
-							$queryBuilder->createNamedParameter(
-								array_column($languages, 'isocode'),
-								Connection::PARAM_STR_ARRAY
-							)
-						)
-					)
-					->execute()->rowCount();
-				if ($rowCount > 0) {
-					$upgradeNecessary = TRUE;
-					break;
-				}
-			}
-		}
-
-		return $upgradeNecessary;
-	}
-
-	/**
-	 * @return array|string[]
-	 */
-	public function getPrerequisites(): array {
-		return [
-			DatabaseUpdatedPrerequisite::class
-		];
-	}
-}
diff --git a/Configuration/TCA/tx_sgmail_domain_model_layout.php b/Configuration/TCA/tx_sgmail_domain_model_layout.php
index 040a8b38ad8af92a76f624188f547c5a811a1599..03a1e0419b56f27dec48f5d638422d83b1302e9d 100644
--- a/Configuration/TCA/tx_sgmail_domain_model_layout.php
+++ b/Configuration/TCA/tx_sgmail_domain_model_layout.php
@@ -32,10 +32,10 @@ $columns = [
 		'crdate' => 'crdate',
 		'cruser_id' => 'cruser_id',
 		'searchFields' => 'name, content',
-		'dividers2tabs' => TRUE,
 		'delete' => 'deleted',
 		'languageField' => 'sys_language_uid',
 		'transOrigPointerField' => 'l10n_parent',
+		'translationSource' => 'l10n_source',
 		'transOrigDiffSourceField' => 'l10n_diffsource',
 		'enablecolumns' => [
 			'disabled' => 'hidden',
@@ -82,9 +82,9 @@ $columns = [
 				'default' => 0,
 				'fieldWizard' => [
 					'selectIcons' => [
-						'disabled' => FALSE,
-					],
-				],
+						'disabled' => FALSE
+					]
+				]
 			]
 		],
 		'l10n_parent' => [
diff --git a/Configuration/TCA/tx_sgmail_domain_model_mail.php b/Configuration/TCA/tx_sgmail_domain_model_mail.php
index 12fe86e4b7344d3cafd1b912b613ef5e183b3dad..7992e211811adde9ed9ce51d9fba8063ad202201 100644
--- a/Configuration/TCA/tx_sgmail_domain_model_mail.php
+++ b/Configuration/TCA/tx_sgmail_domain_model_mail.php
@@ -32,8 +32,7 @@ $columns = [
 		'tstamp' => 'tstamp',
 		'crdate' => 'crdate',
 		'cruser_id' => 'cruser_id',
-		'searchFields' => 'blacklisted, mail_subject, mail_body, to_address, from_address, from_name, bcc_addresses, cc_addresses, extension_key, template_name, sending_time, last_sending_time, language',
-		'dividers2tabs' => TRUE,
+		'searchFields' => 'status, error_message, blacklisted, mail_subject, mail_body, to_address, from_address, from_name, bcc_addresses, cc_addresses, extension_key, template_name, sending_time, last_sending_time, language',
 		'delete' => 'deleted',
 		'enablecolumns' => [
 			'disabled' => 'hidden',
@@ -44,10 +43,32 @@ $columns = [
 	'interface' => [],
 	'types' => [
 		'1' => [
-			'showitem' => 'hidden;;1, blacklisted, priority, to_address, from_address, mail_subject, mail_body, from_name, bcc_addresses, cc_addresses, extension_key, template_name, sending_time, last_sending_time, language, attachments'
+			'showitem' => 'hidden;;1, status, error_message, blacklisted, priority, to_address, from_address, mail_subject, mail_body, from_name, bcc_addresses, cc_addresses, extension_key, template_name, sending_time, last_sending_time, language, attachments'
 		],
 	],
 	'columns' => [
+		'status' => [
+			'exclude' => TRUE,
+			'label' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_mail.status',
+			'config' => [
+				'type' => 'select',
+				'renderType' => 'selectSingle',
+				'items' => [
+					['LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_mail.status.pending', \SGalinski\SgMail\Domain\Model\Mail::STATUS_PENDING],
+					['LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_mail.status.sent', \SGalinski\SgMail\Domain\Model\Mail::STATUS_SENT],
+					['LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_mail.status.error', \SGalinski\SgMail\Domain\Model\Mail::STATUS_ERROR],
+				]
+			]
+		],
+		'error_message' => [
+			'exclude' => TRUE,
+			'label' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_mail.error_message',
+			'config' => [
+				'type' => 'text',
+				'readOnly' => TRUE
+			],
+			'displayCond' => 'FIELD:status:=:' . \SGalinski\SgMail\Domain\Model\Mail::STATUS_ERROR
+		],
 		'hidden' => [
 			'exclude' => TRUE,
 			'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:hidden.I.0',
diff --git a/Configuration/TCA/tx_sgmail_domain_model_template.php b/Configuration/TCA/tx_sgmail_domain_model_template.php
index 7bf38f6fa2911fbc53ba7c7338198314e0862d55..171a03e7752e611f131b34fc2861347cd9114829 100644
--- a/Configuration/TCA/tx_sgmail_domain_model_template.php
+++ b/Configuration/TCA/tx_sgmail_domain_model_template.php
@@ -34,8 +34,11 @@ $columns = [
 		'crdate' => 'crdate',
 		'cruser_id' => 'cruser_id',
 		'searchFields' => 'extension_key, template_name, language, subject, fromName, fromMail, replyTo, to_address',
-		'dividers2tabs' => TRUE,
 		'delete' => 'deleted',
+		'languageField' => 'sys_language_uid',
+		'transOrigPointerField' => 'l18n_parent',
+		'translationSource' => 'l10n_source',
+		'transOrigDiffSourceField' => 'l18n_diffsource',
 		'enablecolumns' => [
 			'disabled' => 'hidden',
 		],
@@ -45,7 +48,7 @@ $columns = [
 	'interface' => [],
 	'types' => [
 		'1' => [
-			'showitem' => 'hidden;;1, extension_key, template_name, language, content, subject, fromName, fromMail, cc, bcc, replyTo, to_address'
+			'showitem' => 'hidden;;1, extension_key, template_name, sys_language_uid, content, subject, fromName, fromMail, cc, bcc, replyTo, to_address'
 		],
 	],
 	'columns' => [
@@ -95,14 +98,6 @@ $columns = [
 				'eval' => 'required, trim'
 			],
 		],
-		'language' => [
-			'exclude' => TRUE,
-			'label' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_template.language',
-			'config' => [
-				'type' => 'input',
-				'eval' => 'required, trim'
-			],
-		],
 		'subject' => [
 			'exclude' => TRUE,
 			'label' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_template.subject',
@@ -156,7 +151,7 @@ $columns = [
 	]
 ];
 if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '10.3.0', '<')) {
-	$columns['interface']['showRecordFieldList'] = 'layout, extension_key, template_name, language, content, subject, fromName, fromMail, cc, bcc, replyTo, to_address';
+	$columns['interface']['showRecordFieldList'] = 'layout, extension_key, template_name, content, subject, fromName, fromMail, cc, bcc, replyTo, to_address';
 }
 
 return $columns;
diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf
index 2564d56ee4fb592a8f87e7d58aea4db9d3df35fe..40b0d1416b8353b283dba48c515e9daa90f3a1a6 100644
--- a/Resources/Private/Language/de.locallang.xlf
+++ b/Resources/Private/Language/de.locallang.xlf
@@ -613,6 +613,10 @@ Die Templates declined und approved der Extension sg_comments sind für alle Dom
 				<source><![CDATA[BCC]]></source>
 				<target><![CDATA[BCC]]></target>
 			</trans-unit>
+			<trans-unit id="backend.preview.error">
+				<source><![CDATA[Preview could not be generated]]></source>
+				<target><![CDATA[Vorschau konnte nicht generiert werden]]></target>
+			</trans-unit>
 		</body>
 	</file>
 </xliff>
diff --git a/Resources/Private/Language/de.locallang_db.xlf b/Resources/Private/Language/de.locallang_db.xlf
index 8e082d7f5462c9f75b1ef64fb4b5b10ebb5f0eed..b2f202ecab246ddbabb4c31b7f170df352df1f3c 100644
--- a/Resources/Private/Language/de.locallang_db.xlf
+++ b/Resources/Private/Language/de.locallang_db.xlf
@@ -45,6 +45,26 @@ Kann bspw. für CSS verwendet werden.]]></target>
 				<source><![CDATA[Mail Queue Entry]]></source>
 				<target><![CDATA[Mail-Queue-Eintrag]]></target>
 			</trans-unit>
+			<trans-unit id="tx_sgmail_domain_model_mail.status">
+				<source><![CDATA[Status]]></source>
+				<target><![CDATA[Status]]></target>
+			</trans-unit>
+			<trans-unit id="tx_sgmail_domain_model_mail.status.pending">
+				<source><![CDATA[Pending]]></source>
+				<target><![CDATA[Wartend]]></target>
+			</trans-unit>
+			<trans-unit id="tx_sgmail_domain_model_mail.status.error">
+				<source><![CDATA[Error]]></source>
+				<target><![CDATA[Fehler]]></target>
+			</trans-unit>
+			<trans-unit id="tx_sgmail_domain_model_mail.status.sent">
+				<source><![CDATA[Sent]]></source>
+				<target><![CDATA[Gesendet]]></target>
+			</trans-unit>
+			<trans-unit id="tx_sgmail_domain_model_mail.error_message">
+				<source><![CDATA[Error message]]></source>
+				<target><![CDATA[Fehlermeldung]]></target>
+			</trans-unit>
 			<trans-unit id="tx_sgmail_domain_model_mail.bcc_addresses" approved="yes">
 				<source><![CDATA[BCC Addresses]]></source>
 				<target><![CDATA[BCC-Adressen]]></target>
@@ -179,4 +199,4 @@ Kann bspw. für CSS verwendet werden.]]></target>
 			</trans-unit>
 		</body>
 	</file>
-</xliff>
\ No newline at end of file
+</xliff>
diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf
index 5a720d077859d626c6826dedaf422e3778284557..d585f2c5a4215d85edac42060a77b558ee0eec0a 100644
--- a/Resources/Private/Language/locallang.xlf
+++ b/Resources/Private/Language/locallang.xlf
@@ -459,6 +459,9 @@ The templates declined and approved of the sg_comments extension are blacklisted
 			<trans-unit id="backend.preview.bcc">
 				<source><![CDATA[BCC]]></source>
 			</trans-unit>
+			<trans-unit id="backend.preview.error">
+				<source><![CDATA[Preview could not be generated]]></source>
+			</trans-unit>
 		</body>
 	</file>
 </xliff>
diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf
index 757ac26970770849122e2f204caed5fa588aca8f..a41b0813792ab9c9e103010938381f7fd44eec57 100644
--- a/Resources/Private/Language/locallang_db.xlf
+++ b/Resources/Private/Language/locallang_db.xlf
@@ -35,6 +35,21 @@ Can be used e.g. for CSS.]]></source>
 			<trans-unit id="tx_sgmail_domain_model_mail">
 				<source><![CDATA[Mail Queue Entry]]></source>
 			</trans-unit>
+			<trans-unit id="tx_sgmail_domain_model_mail.status">
+				<source><![CDATA[Status]]></source>
+			</trans-unit>
+			<trans-unit id="tx_sgmail_domain_model_mail.status.pending">
+				<source><![CDATA[Pending]]></source>
+			</trans-unit>
+			<trans-unit id="tx_sgmail_domain_model_mail.status.error">
+				<source><![CDATA[Error]]></source>
+			</trans-unit>
+			<trans-unit id="tx_sgmail_domain_model_mail.status.sent">
+				<source><![CDATA[Sent]]></source>
+			</trans-unit>
+			<trans-unit id="tx_sgmail_domain_model_mail.error_message">
+				<source><![CDATA[Error message]]></source>
+			</trans-unit>
 			<trans-unit id="tx_sgmail_domain_model_mail.bcc_addresses">
 				<source><![CDATA[BCC Addresses]]></source>
 			</trans-unit>
@@ -136,4 +151,4 @@ Can be used e.g. for CSS.]]></source>
 			</trans-unit>
 		</body>
 	</file>
-</xliff>
\ No newline at end of file
+</xliff>
diff --git a/Resources/Private/Partials/ButtonBar.html b/Resources/Private/Partials/ButtonBar.html
index b63090afaf97f180ac634edb5cf59a9b09c090a8..430943650907fd00df2a0ad74742717f2dc7a95d 100644
--- a/Resources/Private/Partials/ButtonBar.html
+++ b/Resources/Private/Partials/ButtonBar.html
@@ -1,14 +1,14 @@
-	<f:for each="{buttons}" as="buttonGroup">
-		<f:if condition="{buttonGroup -> f:count()} > 1">
-			<f:then>
-				<div class="btn-group" role="group" aria-label="">
-					<f:for each="{buttonGroup}" as="button">
-						{button -> f:format.raw()}
-					</f:for>
-				</div>
-			</f:then>
-			<f:else>
-				{buttonGroup.0 -> f:format.raw()}
-			</f:else>
-		</f:if>
-	</f:for>
+<f:for each="{buttons}" as="buttonGroup">
+	<f:if condition="{buttonGroup -> f:count()} > 1">
+		<f:then>
+			<div class="btn-group" role="group" aria-label="">
+				<f:for each="{buttonGroup}" as="button">
+					{button -> f:format.raw()}
+				</f:for>
+			</div>
+		</f:then>
+		<f:else>
+			{buttonGroup.0 -> f:format.raw()}
+		</f:else>
+	</f:if>
+</f:for>
diff --git a/Resources/Private/Partials/Layout/Empty.html b/Resources/Private/Partials/Layout/Empty.html
index ecceff62b936325a2c1d6c89b0229d3bcbb51a53..33eeda0bff3262c2e084834a5b90e1a49aaf14cb 100644
--- a/Resources/Private/Partials/Layout/Empty.html
+++ b/Resources/Private/Partials/Layout/Empty.html
@@ -1,3 +1,3 @@
 <p>
-	{f:translate(key:'backend.no_layout_entries')}
+	<f:translate key="backend.no_layout_entries" />
 </p>
diff --git a/Resources/Private/Partials/Mail/Empty.html b/Resources/Private/Partials/Mail/Empty.html
index 00da31387f53280c02abe166cd4b380ffef57fc6..4700fbbc4c8c57338e9913306c8a349c582a7c2b 100644
--- a/Resources/Private/Partials/Mail/Empty.html
+++ b/Resources/Private/Partials/Mail/Empty.html
@@ -1,5 +1,5 @@
 <div class="row">
 	<p>
-		<h3>{f:translate(key:'backend.no_site_root')}</h3>
+		<h3><f:translate key="backend.no_site_root" /></h3>
 	</p>
 </div>
diff --git a/Resources/Private/Partials/Module/DocHeader.html b/Resources/Private/Partials/Module/DocHeader.html
index 549a53ade7d49d868fe93729d983c4f785974671..64b85c11219362947c4d5869ae79667be3052d3f 100644
--- a/Resources/Private/Partials/Module/DocHeader.html
+++ b/Resources/Private/Partials/Module/DocHeader.html
@@ -1,29 +1,3 @@
-<f:comment><!--
-  ~
-  ~ 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!
-  --></f:comment>
-
-<!DOCTYPE html>
 <html
 	xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
 	xmlns:mail="http://typo3.org/ns/SGalinski/SgMail/ViewHelpers"
diff --git a/Resources/Private/Partials/Queue/Empty.html b/Resources/Private/Partials/Queue/Empty.html
index 99a38fcd2506bf4d0656839e1259f10fc55fed5c..bd76ddc0c37c9e264b559a7c6012dfc36f05e53e 100644
--- a/Resources/Private/Partials/Queue/Empty.html
+++ b/Resources/Private/Partials/Queue/Empty.html
@@ -1,3 +1,3 @@
 <p>
-	{f:translate(key:'backend.no_queue_entries')}
+	<f:translate key="backend.no_queue_entries" />
 </p>
diff --git a/Resources/Private/Partials/Queue/Filter.html b/Resources/Private/Partials/Queue/Filter.html
index e5a5b5071c025c5b8799ae29a7c7c13917392bb5..f6f78d0013ca6e077e71a0fb84f6ca10d6af4727 100644
--- a/Resources/Private/Partials/Queue/Filter.html
+++ b/Resources/Private/Partials/Queue/Filter.html
@@ -14,18 +14,9 @@
 							<f:then>
 								<sgm:be.menus.actionMenuOptionGroup label="{extensionKey}">
 									<f:for each="{extension}" as="template">
-										<f:if condition="{selectedTemplateFilter} == {template.name} && {selectedExtensionFilter} == {extensionKey}">
-											<f:then>
-												<option value="{extensionKey}###{template.name}" selected="selected">
-													{f:if(condition: '{template.is_manual}', then:'* ')}{template.name}
-												</option>
-											</f:then>
-											<f:else>
-												<option value="{extensionKey}###{template.name}">
-													{f:if(condition: '{template.is_manual}', then:'* ')}{template.name}
-												</option>
-											</f:else>
-										</f:if>
+										<option value="{extensionKey}###{template.name}"{f:if(condition:'{selectedTemplateFilter} == {template.name} && {selectedExtensionFilter} == {extensionKey}',then:' selected="selected"')}>
+											{f:if(condition: '{template.is_manual}', then:'* ')}{template.name}
+										</option>
 									</f:for>
 								</sgm:be.menus.actionMenuOptionGroup>
 							</f:then>
@@ -54,7 +45,13 @@
 					<f:translate key="backend.filters.fields" />
 					<f:translate key="backend.filter.fields.description" />
 				</label>
-				<f:form.select class="form-control" multiple="1" size="9" property="filterFields" optionValueField="value" options="{filterFields}" id="filter-fields" />
+				<f:form.select class="form-control"
+							   multiple="1"
+							   size="9"
+							   property="filterFields"
+							   optionValueField="value"
+							   options="{filterFields}"
+							   id="filter-fields" />
 			</div>
 		</div>
 		<div class="col-xs-12 col-md-4">
@@ -64,7 +61,10 @@
 					<f:translate key="backend.filter.date_from" />
 				</label>
 				<div class="form-control-clearable">
-					<f:form.textfield property="filterFromDate" id="filter-from-date" data="{date-type: 'datetime'}" class="reset-me form-control t3js-datetimepicker t3js-clearable hasDefaultValue" />
+					<f:form.textfield property="filterFromDate"
+									  id="filter-from-date"
+									  data="{date-type: 'datetime'}"
+									  class="reset-me form-control t3js-datetimepicker t3js-clearable hasDefaultValue" />
 					<button type="button" class="close" tabindex="-1" aria-hidden="true" style="display: none;">
 						<span class="fa fa-times"></span>
 					</button>
@@ -80,7 +80,10 @@
 					<f:translate key="backend.filter.date_to" />
 				</label>
 				<div class="form-control-clearable">
-					<f:form.textfield property="filterToDate" id="filter-to-date" data="{date-type: 'datetime'}" class="reset-me form-control t3js-datetimepicker t3js-clearable hasDefaultValue" />
+					<f:form.textfield property="filterToDate"
+									  id="filter-to-date"
+									  data="{date-type: 'datetime'}"
+									  class="reset-me form-control t3js-datetimepicker t3js-clearable hasDefaultValue" />
 					<button type="button" class="close" tabindex="-1" aria-hidden="true" style="display: none;">
 						<span class="fa fa-times"></span>
 					</button>
@@ -93,32 +96,50 @@
 			</div>
 			<div class="form-group">
 				<label class="radio-inline">
-					<f:form.radio property="filterSent" id="filters-all" value="0" checked="{f:if(condition: '{filters.filterSent} == \'0\'', then: '1')}" />
+					<f:form.radio property="filterSent"
+								  id="filters-all"
+								  value="0"
+								  checked="{f:if(condition: '{filters.filterSent} == \'0\'', then: '1')}" />
 					<f:translate key="backend.all" />
 				</label>
 				<label class="radio-inline">
-					<f:form.radio property="filterSent" id="filters-sent" value="1" checked="{f:if(condition: '{filters.filterSent} == \'1\'', then: '1')}" />
+					<f:form.radio property="filterSent"
+								  id="filters-sent"
+								  value="1"
+								  checked="{f:if(condition: '{filters.filterSent} == \'1\'', then: '1')}" />
 					<f:translate key="backend.sent" />
 				</label>
 				<label class="radio-inline">
-					<f:form.radio property="filterSent" id="filters-notsent" value="2" checked="{f:if(condition: '{filters.filterSent} == \'2\'', then: '1')}" />
+					<f:form.radio property="filterSent"
+								  id="filters-notsent"
+								  value="2"
+								  checked="{f:if(condition: '{filters.filterSent} == \'2\'', then: '1')}" />
 					<f:translate key="backend.not_sent" />
 				</label>
 			</div>
 			<div class="form-group">
-				<f:form.checkbox property="filterBlacklist" id="filters-blacklisted" value="1" checked="{f:if(condition: '{filters.filterBlacklist} == \'1\'', then: '1')}" />
+				<f:form.checkbox property="filterBlacklist"
+								 id="filters-blacklisted"
+								 value="1"
+								 checked="{f:if(condition: '{filters.filterBlacklist} == \'1\'', then: '1')}" />
 				<f:translate key="backend.blacklisted" />
 			</div>
 		</div>
 		<div class="form-group">
 			<div class="col-md-12">
-				<f:form.button class="filter-btn btn btn-success form-group col-xs-12 col-md-12" type="submit">
+				<f:form.button class="filter-btn btn btn-success form-group col-xs-12 col-md-12"
+							   type="submit">
 					<f:translate key="backend.filter.filter" />
 				</f:form.button>
-				<f:form.button class="filter-btn btn btn-info form-group col-xs-12 col-md-12" type="submit" name="action" value="export">
+				<f:form.button class="filter-btn btn btn-info form-group col-xs-12 col-md-12"
+							   type="submit"
+							   name="action"
+							   value="export">
 					<f:translate key="backend.button_download_csv" />
 				</f:form.button>
-				<f:form.button id="filter-reset-btn" class="filter-btn btn btn-danger form-group col-xs-12 col-md-12" type="reset">
+				<f:form.button id="filter-reset-btn"
+							   class="filter-btn btn btn-danger form-group col-xs-12 col-md-12"
+							   type="reset">
 					<f:translate key="backend.button_reset_filter" />
 				</f:form.button>
 			</div>
diff --git a/Resources/Private/Templates/Configuration/Index.html b/Resources/Private/Templates/Configuration/Index.html
index dfeb25ab19cf9d84cb2bbdb23a9de3b2d42cfe37..7f50ed97cf90ba5c92eabf6abcca052c44f6608e 100644
--- a/Resources/Private/Templates/Configuration/Index.html
+++ b/Resources/Private/Templates/Configuration/Index.html
@@ -15,15 +15,17 @@
 					<f:translate key="backend.create.info_header" />
 				</div>
 				<div class="panel-body">
-					<f:format.html>
-						<f:translate key="backend.create.info" />
-					</f:format.html>
+					<f:format.html><f:translate key="backend.create.info" /></f:format.html>
 				</div>
 			</div>
 		</div>
 	</div>
 
-	<f:form action="{f:if(condition: '{editMode}', then: 'edit', else: 'create')}" controller="Configuration" method="post" objectName="configuration" object="{configuration}">
+	<f:form action="{f:if(condition: '{editMode}', then: 'edit', else: 'create')}"
+			controller="Configuration"
+			method="post"
+			objectName="configuration"
+			object="{configuration}">
 		<div class="row">
 			<div class="col-xs-12 col-md-10 col-md-offset-1">
 				<f:form.hidden name="extensionKey" value="{selectedExtensionKey}"/>
@@ -31,25 +33,45 @@
 				<f:form.hidden name="oldExtensionKey" property="oldExtensionKey" value="{selectedExtensionKey}"/>
 				<div class="form-group">
 					<label for="extensionKey"><f:translate key="backend.create.extensionKey" /></label>
-					<f:form.textfield class="form-control" property="extensionKey" id="extensionKey" required="TRUE" value="{extensionKey}" />
+					<f:form.textfield class="form-control"
+									  property="extensionKey"
+									  id="extensionKey"
+									  required="TRUE"
+									  value="{extensionKey}" />
 				</div>
 				<div class="form-group">
 					<label for="templateName"><f:translate key="backend.create.templateName" /></label>
-					<f:form.textfield class="form-control" property="templateName" id="templateName" required="TRUE" value="{templateName}" />
+					<f:form.textfield class="form-control"
+									  property="templateName"
+									  id="templateName"
+									  required="TRUE"
+									  value="{templateName}" />
 				</div>
 				<div class="form-group">
 					<label for="csv"><f:translate key="backend.create.csv" /></label>
-					<f:form.textarea rows="5" class="form-control" property="csv" id="csv" value="{csv}" />
+					<f:form.textarea rows="5"
+									 class="form-control"
+									 property="csv"
+									 id="csv"
+									 value="{csv}" />
 				</div>
 				<div class="form-group">
 					<label for="subject"><f:translate key="backend.create.subject" /></label>
-					<f:form.textfield class="form-control" property="subject" id="subject" value="{subject}" />
+					<f:form.textfield class="form-control"
+									  property="subject"
+									  id="subject"
+									  value="{subject}" />
 				</div>
 				<div class="form-group">
 					<label for="description"><f:translate key="backend.create.description" /></label>
-					<f:form.textarea rows="5" class="form-control" property="description" id="description" value="{description}" />
+					<f:form.textarea rows="5"
+									 class="form-control"
+									 property="description"
+									 id="description"
+									 value="{description}" />
 				</div>
-				<f:form.submit class="btn-primary btn form-group col-xs-12 col-md-2 col-md-offset-10" value="{f:translate(key:'backend.create.save')}" />
+				<f:form.submit class="btn-primary btn form-group col-xs-12 col-md-2 col-md-offset-10"
+							   value="{f:translate(key:'backend.create.save')}" />
 			</div>
 		</div>
 	</f:form>
diff --git a/Resources/Private/Templates/Layout/Index.html b/Resources/Private/Templates/Layout/Index.html
index 635d48c2893512ad5e4ee12be7b7bc7f9a1589b9..2742a994e0031eff98f26f730c512abfc900a1ed 100644
--- a/Resources/Private/Templates/Layout/Index.html
+++ b/Resources/Private/Templates/Layout/Index.html
@@ -3,7 +3,10 @@
 <f:layout name="Default" />
 
 <f:section name="iconButtons">
-	<be:link.newRecord table="tx_sgmail_domain_model_layout" pid="{pageUid}" class="btn btn-default btn-sm" title="{f:translate(key: 'backend.button_create_layout')}">
+	<be:link.newRecord table="tx_sgmail_domain_model_layout"
+					   pid="{pageUid}"
+					   class="btn btn-default btn-sm"
+					   title="{f:translate(key: 'backend.button_create_layout')}">
 		<core:icon identifier="actions-document-new" />
 	</be:link.newRecord>
 	<f:if condition="{pasteButton}">
@@ -27,7 +30,8 @@
 						<table data-table="tx_sgmail_domain_model_layout" class="table table-striped table-hover">
 							<tbody>
 								<f:for each="{layouts}" as="layout">
-									<tr data-uid="{layout.uid}" class="{f:if(condition: '{layout.default}', then: 'success', else: '')}">
+									<tr data-uid="{layout.uid}"
+										class="{f:if(condition: '{layout.default}', then: 'success', else: '')}">
 										<td nowrap="nowrap" class="col-icon">
 											<core:iconForRecord row="{layout}" table="tx_sgmail_domain_model_layout" />
 										</td>
@@ -39,9 +43,7 @@
 											</be:link.editRecord>
 										</td>
 										<td nowrap="nowrap" class="col-control">
-											<f:format.raw>
-												<sg:backend.control table="tx_sgmail_domain_model_layout" row="{layout}" clipboard="1" />
-											</f:format.raw>
+											<f:format.raw><sg:backend.control table="tx_sgmail_domain_model_layout" row="{layout}" clipboard="1" /></f:format.raw>
 										</td>
 									</tr>
 								</f:for>
@@ -65,7 +67,8 @@
 						<f:for each="{pages}" as="page">
 							<tr data-uid="{page.pid}">
 								<td nowrap="nowrap" class="col-title">
-									<f:link.action action="index" additionalParams="{id: page.uid, returnUrl: returnUrl}">
+									<f:link.action action="index"
+												   additionalParams="{id: page.uid, returnUrl: returnUrl}">
 										<core:iconForRecord row="{page}" table="pages" />
 										{page._thePathFull}
 									</f:link.action>
diff --git a/Resources/Private/Templates/Mail/Empty.html b/Resources/Private/Templates/Mail/Empty.html
index c39bf8639ddeb268eb99722aa1d9e5fd0e764c19..f58331a5fd546b79cb9510ce801b282359cf9fe9 100644
--- a/Resources/Private/Templates/Mail/Empty.html
+++ b/Resources/Private/Templates/Mail/Empty.html
@@ -2,6 +2,6 @@
 
 <f:section name="content">
 	<div class="alert alert-warning">
-		{f:translate(key:'backend.no_extensions')}
+		<f:translate key="backend.no_extensions" />
 	</div>
 </f:section>
diff --git a/Resources/Private/Templates/Newsletter/Empty.html b/Resources/Private/Templates/Newsletter/Empty.html
index c39bf8639ddeb268eb99722aa1d9e5fd0e764c19..f58331a5fd546b79cb9510ce801b282359cf9fe9 100644
--- a/Resources/Private/Templates/Newsletter/Empty.html
+++ b/Resources/Private/Templates/Newsletter/Empty.html
@@ -2,6 +2,6 @@
 
 <f:section name="content">
 	<div class="alert alert-warning">
-		{f:translate(key:'backend.no_extensions')}
+		<f:translate key="backend.no_extensions" />
 	</div>
 </f:section>
diff --git a/Resources/Private/Templates/Newsletter/Index.html b/Resources/Private/Templates/Newsletter/Index.html
index b52c9989b4f34faa969531fa26283aa84dac746c..06cd88939b20cac6e346d53095ec40c51c2a1112 100644
--- a/Resources/Private/Templates/Newsletter/Index.html
+++ b/Resources/Private/Templates/Newsletter/Index.html
@@ -256,37 +256,79 @@
 									</h3>
 									<div class="col-md-12">
 										<div class="row form-group">
-											<label for="parameters-templates-{key}-layout" class="">{f:translate(key:'backend.layout')}</label>
-											<f:form.select id="parameters-templates-{key}-layout" class="form-control"
- value="{languageTemplate.layout}" options="{layoutOptions}" name="parameters[templates][{key}][layout]"/>
+											<label for="parameters-templates-{key}-layout">
+												<f:translate key="backend.layout" />
+											</label>
+											<f:form.select id="parameters-templates-{key}-layout"
+														   class="form-control"
+														   value="{languageTemplate.layout}"
+														   options="{layoutOptions}"
+														   name="parameters[templates][{key}][layout]"/>
 										</div>
 										<div class="row form-group">
-											<label for="parameters[templates][{key}][fromName]" class="">{f:translate(key:'backend.fromName')}</label>
-											<f:form.textfield type="text" class="form-control" value="{languageTemplate.fromName}" name="parameters[templates][{key}][fromName]" />
+											<label for="parameters-templates-{key}-fromName">
+												<f:translate key="backend.fromName" />
+											</label>
+											<f:form.textfield id="parameters-templates-{key}-fromName"
+															  class="form-control"
+															  value="{languageTemplate.fromName}"
+															  name="parameters[templates][{key}][fromName]" />
 										</div>
 										<div class="row form-group">
-											<label for="parameters[templates][{key}][fromMail]" class="">{f:translate(key:'backend.fromMail')}</label>
-											<f:form.textfield type="email" class="form-control" value="{languageTemplate.fromMail}" name="parameters[templates][{key}][fromMail]" />
+											<label for="parameters-templates-{key}-fromMail">
+												<f:translate key="backend.fromMail" />
+											</label>
+											<f:form.textfield id="parameters-templates-{key}-fromMail"
+															  type="email"
+															  class="form-control"
+															  value="{languageTemplate.fromMail}"
+															  name="parameters[templates][{key}][fromMail]" />
 										</div>
 										<div class="row form-group">
-											<label for="parameters[templates][{key}][cc]" class="">{f:translate(key:'backend.cc')}</label>
-											<f:form.textfield type="text" class="form-control" value="{languageTemplate.cc}" name="parameters[templates][{key}][cc]" />
+											<label for="parameters-templates-{key}-cc">
+												<f:translate key="backend.cc" />
+											</label>
+											<f:form.textfield id="parameters-templates-{key}-cc"
+															  class="form-control"
+															  value="{languageTemplate.cc}"
+															  name="parameters[templates][{key}][cc]" />
 										</div>
 										<div class="row form-group">
-											<label for="parameters[templates][{key}][bcc]" class="">{f:translate(key:'backend.bcc')}</label>
-											<f:form.textfield type="text" class="form-control" value="{languageTemplate.bcc}" name="parameters[templates][{key}][bcc]" />
+											<label for="parameters-templates-{key}-bcc">
+												<f:translate key="backend.bcc" />
+											</label>
+											<f:form.textfield id="parameters-templates-{key}-bcc"
+															  class="form-control"
+															  value="{languageTemplate.bcc}"
+															  name="parameters[templates][{key}][bcc]" />
 										</div>
 										<div class="row form-group">
-											<label for="parameters[templates][{key}][replyTo]" class="">{f:translate(key:'backend.replyTo')}</label>
-											<f:form.textfield type="text" class="form-control" value="{languageTemplate.replyTo}" name="parameters[templates][{key}][replyTo]" />
+											<label for="parameters-templates-{key}-replyTo">
+												<f:translate key="backend.replyTo" />
+											</label>
+											<f:form.textfield id="parameters-templates-{key}-replyTo"
+															  class="form-control"
+															  value="{languageTemplate.replyTo}"
+															  name="parameters[templates][{key}][replyTo]" />
 										</div>
 										<div class="row form-group">
-											<label for="parameters[templates][{key}][subject]" class="">{f:translate(key:'backend.subject')}</label>
-											<f:form.textfield type="text" class="form-control" value="{languageTemplate.subject}" name="parameters[templates][{key}][subject]" />
+											<label for="parameters-templates-{key}-subject">
+												<f:translate key="backend.subject" />
+											</label>
+											<f:form.textfield id="parameters-templates-{key}-subject"
+															  class="form-control"
+															  value="{languageTemplate.subject}"
+															  name="parameters[templates][{key}][subject]" />
 										</div>
 										<div class="row form-group">
-											<label for="parameters[templates][{key}][content]" class="">{f:translate(key:'backend.content')}</label>
-											<f:form.textarea class="form-control" rows="15" name="parameters[templates][{key}][content]" value="{languageTemplate.content}" />
+											<label for="parameters-templates-{key}-content">
+												<f:translate key="backend.content" />
+											</label>
+											<f:form.textarea id="parameters-templates-{key}-content"
+															 class="form-control"
+															 rows="15"
+															 name="parameters[templates][{key}][content]"
+															 value="{languageTemplate.content}" />
 										</div>
 									</div>
 								</div>
@@ -294,10 +336,19 @@
 						</div>
 					</f:for>
 					<div class="form-group">
-						<f:form.submit name="sendDirectly" id="newsletter-send-real-emails-button" class="btn-success btn form-group" value="{f:translate(key:'backend.send_newsletter')}" />
-						<f:form.submit class="btn-primary btn form-group" id="newsletter-send-preview-emails-button" value="{f:translate(key:'backend.send_test_newsletter')}" />
-						<f:form.textfield name="parameters[emailAddress]" class="email-input form-group" value="{beUserMail}" />
-						<f:form.hidden name="sendRealEmails" id="newsletter-send-real-emails-hidden-field" value="0" />
+						<f:form.submit name="sendDirectly"
+									   id="newsletter-send-real-emails-button"
+									   class="btn-success btn form-group"
+									   value="{f:translate(key:'backend.send_newsletter')}" />
+						<f:form.submit class="btn-primary btn form-group"
+									   id="newsletter-send-preview-emails-button"
+									   value="{f:translate(key:'backend.send_test_newsletter')}" />
+						<f:form.textfield name="parameters[emailAddress]"
+										  class="email-input form-group"
+										  value="{beUserMail}" />
+						<f:form.hidden name="sendRealEmails"
+									   id="newsletter-send-real-emails-hidden-field"
+									   value="0" />
 						<f:form.hidden name="parameters[selectedLanguage]" value="{selectedLanguage}" />
 						<f:form.hidden name="parameters[selectedTemplate]" value="{selectedTemplateKey}" />
 						<f:form.hidden name="parameters[selectedExtensionKey]" value="{selectedTemplate.extension}" />
@@ -320,7 +371,10 @@
 							<f:for each="{pages}" as="page">
 								<tr data-uid="{page.pid}">
 									<td nowrap="nowrap" class="col-title">
-										<f:link.action class="sg-mail_pageswitch" action="index" additionalParams="{id: page.uid, returnUrl: returnUrl}" additionalAttributes="{data-page: page.uid, data-path: page.path}">
+										<f:link.action class="sg-mail_pageswitch"
+													   action="index"
+													   additionalParams="{id: page.uid, returnUrl: returnUrl}"
+													   additionalAttributes="{data-page: page.uid, data-path: page.path}">
 											<core:iconForRecord table="pages" row="{page}" />
 											{page._thePathFull}
 										</f:link.action>
@@ -336,14 +390,24 @@
 </f:section>
 
 <f:section name="iconButtons">
-	<f:link.action class="btn btn-default btn-sm" controller="Configuration" action="index" arguments="{mode: 'new', selectedTemplate: selectedTemplateKey, selectedExtension: selectedTemplate.extension}">
+	<f:link.action class="btn btn-default btn-sm"
+				   controller="Configuration"
+				   action="index"
+				   arguments="{mode: 'new', selectedTemplate: selectedTemplateKey, selectedExtension: selectedTemplate.extension}">
 		<core:icon identifier="actions-document-new" />
 	</f:link.action>
 	<f:if condition="{isManual}">
-		<f:link.action class="btn btn-default btn-sm" controller="Configuration" action="index" arguments="{mode: 'edit', selectedTemplate: selectedTemplateKey, selectedExtension: selectedTemplate.extension}">
+		<f:link.action class="btn btn-default btn-sm"
+					   controller="Configuration"
+					   action="index"
+					   arguments="{mode: 'edit', selectedTemplate: selectedTemplateKey, selectedExtension: selectedTemplate.extension}">
 			<core:icon identifier="actions-document-open" />
 		</f:link.action>
-		<f:link.action class="btn btn-default btn-sm" id="delete-template-btn" controller="Configuration" action="delete" arguments="{selectedTemplate: selectedTemplateKey, selectedExtension: selectedTemplate.extension}">
+		<f:link.action class="btn btn-default btn-sm"
+					   id="delete-template-btn"
+					   controller="Configuration"
+					   action="delete"
+					   arguments="{selectedTemplate: selectedTemplateKey, selectedExtension: selectedTemplate.extension}">
 			<core:icon identifier="actions-edit-delete" />
 		</f:link.action>
 	</f:if>
diff --git a/Resources/Private/Templates/Queue/Index.html b/Resources/Private/Templates/Queue/Index.html
index 90dbe3c67c239cdb6e3c507235bb0bd9b2e499d8..104e3058fb1910673685f0ed65f25b6cf16a6358 100644
--- a/Resources/Private/Templates/Queue/Index.html
+++ b/Resources/Private/Templates/Queue/Index.html
@@ -90,15 +90,16 @@
 												</f:then>
 												<f:else>
 													<f:link.action class="btn btn-default btn-send-now"
-																   controller="Queue" action="sendMail"
-																   arguments="{uid: mail.uid, selectedTemplate: selectedTemplateKey, selectedExtension: selectedExtensionKey}">
+																   controller="Queue"
+																   action="sendMail"
+																   arguments="{mail: mail, selectedTemplate: selectedTemplateKey, selectedExtension: selectedExtensionKey}">
 														<core:icon identifier="actions-document-import-t3d"/>
 														<f:translate key="backend.send_now"/>
 													</f:link.action>
 												</f:else>
 											</f:if>
 											<button class="btn btn-default btn-preview"
-													onClick="MailPreviewWindow{mail.uid}=window.open('{f:uri.action( controller: 'Queue', action: 'preview', noCacheHash: true, arguments: {uid: mail.uid, selectedTemplate: selectedTemplateKey, selectedExtension: selectedExtensionKey})}','MailPreviewWindow{mail.uid}','width=1200,height=768'); return false;">
+													onClick="MailPreviewWindow{mail.uid}=window.open('{f:uri.action( controller: 'Queue', action: 'preview', noCacheHash: true, arguments: {mail: mail})}','MailPreviewWindow{mail.uid}','width=1200,height=768'); return false;">
 												<core:icon identifier="actions-view-page"/>
 											</button>
 										</td>
diff --git a/Resources/Private/Templates/Queue/Preview.html b/Resources/Private/Templates/Queue/Preview.html
index ee57f58fde17f7d903aa2afe96641b35b1e57bec..877412fa9848c895b905a4d92e185e83868b554e 100644
--- a/Resources/Private/Templates/Queue/Preview.html
+++ b/Resources/Private/Templates/Queue/Preview.html
@@ -1,74 +1,81 @@
 <f:layout name="Preview"/>
 
 <f:section name="mailPreview">
-	<div class="mail-header">
-		<table>
-			<tr>
-				<th>
-					<f:translate key="backend.preview.date"/>
-				</th>
-				<td>
-					<f:format.date format="d.m.Y H:i">
-						<f:format.stripTags>{mail.sendingTime}</f:format.stripTags>
-					</f:format.date>
-				</td>
-			</tr>
+	<f:if condition="{mail} && !{mail.blacklisted}">
+		<f:then>
+			<div class="mail-header">
+				<table>
+					<tr>
+						<th>
+							<f:translate key="backend.preview.date"/>
+						</th>
+						<td>
+							<f:format.date format="d.m.Y H:i">
+								<f:format.stripTags>{mail.sendingTime}</f:format.stripTags>
+							</f:format.date>
+						</td>
+					</tr>
 
-			<tr>
-				<th>
-					<f:translate key="backend.preview.from"/>
-				</th>
-				<td>
-					<f:format.stripTags>{mail.fromName}</f:format.stripTags>
-					&lt;<f:format.stripTags>{mail.fromAddress}</f:format.stripTags>&gt;
-				</td>
-			</tr>
+					<tr>
+						<th>
+							<f:translate key="backend.preview.from"/>
+						</th>
+						<td>
+							<f:format.stripTags>{mail.fromName}</f:format.stripTags>
+							&lt;<f:format.stripTags>{mail.fromAddress}</f:format.stripTags>&gt;
+						</td>
+					</tr>
 
-			<tr>
-				<th>
-					<f:translate key="backend.preview.subject"/>
-				</th>
-				<td>
-					<strong>
-						<f:format.stripTags>{mail.mailSubject}</f:format.stripTags>
-					</strong>
-				</td>
-			</tr>
+					<tr>
+						<th>
+							<f:translate key="backend.preview.subject"/>
+						</th>
+						<td>
+							<strong>
+								<f:format.stripTags>{mail.mailSubject}</f:format.stripTags>
+							</strong>
+						</td>
+					</tr>
 
-			<tr>
-				<th>
-					<f:translate key="backend.preview.to"/>
-				</th>
-				<td class="ng-binding">
-					<f:format.stripTags>{mail.toAddress}</f:format.stripTags>
-				</td>
-			</tr>
+					<tr>
+						<th>
+							<f:translate key="backend.preview.to"/>
+						</th>
+						<td class="ng-binding">
+							<f:format.stripTags>{mail.toAddress}</f:format.stripTags>
+						</td>
+					</tr>
 
-			<f:if condition="{mail.ccAddresses}">
-				<tr>
-					<th>
-						<f:translate key="backend.preview.cc"/>
-					</th>
-					<td class="ng-binding">
-						<f:format.stripTags>{mail.ccAddresses}</f:format.stripTags>
-					</td>
-				</tr>
-			</f:if>
+					<f:if condition="{mail.ccAddresses}">
+						<tr>
+							<th>
+								<f:translate key="backend.preview.cc"/>
+							</th>
+							<td class="ng-binding">
+								<f:format.stripTags>{mail.ccAddresses}</f:format.stripTags>
+							</td>
+						</tr>
+					</f:if>
 
-			<f:if condition="{mail.bccAddresses}">
-				<tr>
-					<th>
-						<f:translate key="backend.preview.bcc"/>
-					</th>
-					<td class="ng-binding">
-						<f:format.stripTags>{mail.bccAddresses}</f:format.stripTags>
-					</td>
-				</tr>
-			</f:if>
-		</table>
-	</div>
+					<f:if condition="{mail.bccAddresses}">
+						<tr>
+							<th>
+								<f:translate key="backend.preview.bcc"/>
+							</th>
+							<td class="ng-binding">
+								<f:format.stripTags>{mail.bccAddresses}</f:format.stripTags>
+							</td>
+						</tr>
+					</f:if>
+				</table>
+			</div>
 
-	<div class="mail-body">
-		<iframe class="mail-body-iframe" srcdoc="{mail.mailBody}" sandbox></iframe>
-	</div>
+			<div class="mail-body">
+				<iframe class="mail-body-iframe" srcdoc="{mail.mailBody}" sandbox></iframe>
+			</div>
+		</f:then>
+		<f:else>
+			<f:translate key="backend.preview.error" />
+		</f:else>
+	</f:if>
 </f:section>
diff --git a/ext_localconf.php b/ext_localconf.php
index e9be793e768259e05c179b3aa5e8983829756df0..82f7125e32946d80fbe25caab7b53dc90e1c8207 100644
--- a/ext_localconf.php
+++ b/ext_localconf.php
@@ -28,10 +28,10 @@ call_user_func(
 		// add upgrade wizard for moving all db entries to their respected siteroot
 		$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\UpdatePidToSiteRoot::IDENTIFIER] = \SGalinski\SgMail\Updates\UpdatePidToSiteRoot::class;
 		$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\UpdateSendingTimes::IDENTIFIER] = \SGalinski\SgMail\Updates\UpdateSendingTimes::class;
-		$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\UpdateLanguages::IDENTIFIER] = \SGalinski\SgMail\Updates\UpdateLanguages::class;
-		$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\UpdateGermanAsDefault::IDENTIFIER] = \SGalinski\SgMail\Updates\UpdateGermanAsDefault::class;
 		$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\MigrateSchedulerTasks::IDENTIFIER] = \SGalinski\SgMail\Updates\MigrateSchedulerTasks::class;
 		$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\MigrateFinishersUpgrade::IDENTIFIER] = \SGalinski\SgMail\Updates\MigrateFinishersUpgrade::class;
+		$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\SendStatusUpdate::IDENTIFIER] = \SGalinski\SgMail\Updates\SendStatusUpdate::class;
+		$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\LanguageMigrationUpdate::IDENTIFIER] = \SGalinski\SgMail\Updates\LanguageMigrationUpdate::class;
 
 		if (TYPO3_MODE === 'BE') {
 			\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScriptSetup(
diff --git a/ext_tables.sql b/ext_tables.sql
index c8b4ccf5be61092e4be69fbbaf9c8c5729fea475..04dc4fae6fdb1066553b1c7e8216a654b2ac1576 100644
--- a/ext_tables.sql
+++ b/ext_tables.sql
@@ -14,7 +14,9 @@ CREATE TABLE tx_sgmail_domain_model_mail (
 	last_sending_time int(11) unsigned DEFAULT '0' NOT NULL,
 	language varchar(255) DEFAULT '' NOT NULL,
 	blacklisted tinyint(4) unsigned DEFAULT '0' NOT NULL,
-	attachments int(11) unsigned DEFAULT '0' NOT NULL
+	attachments int(11) unsigned DEFAULT '0' NOT NULL,
+	status varchar(255) DEFAULT 'pending' NOT NULL,
+	error_message text
 );
 
 CREATE TABLE tx_sgmail_domain_model_template (
@@ -28,7 +30,6 @@ CREATE TABLE tx_sgmail_domain_model_template (
 	cc varchar(255) DEFAULT '' NOT NULL,
 	bcc varchar(255) DEFAULT '' NOT NULL,
 	reply_to varchar(255) DEFAULT '' NOT NULL,
-	language varchar(30) DEFAULT '' NOT NULL,
 	content text NOT NULL
 );