<?php
namespace App\Library\Subscribers;
use App\Library\Database;
use App\Library\Event\demoSendEvent;
use App\Library\Event\GrapperProcessEvent;
use App\Library\Event\GrapperQueueEvent;
use App\Library\Event\testEvent;
use App\Library\Helper;
use App\Library\Mailer as MailHandler;
use App\Library\TemplateLibrary;
use App\models\acount;
use App\models\blacklistEmail;
use App\models\eadr;
use App\models\emain;
use App\models\grapperEmailTemplate;
use App\models\grapperMailLog;
use DateInterval;
use DateTime;
use Doctrine\DBAL\Exception as BaseException;
use Error;
use ErrorException;
use Exception;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Exception\RfcComplianceException;
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
use Twig\Loader\ArrayLoader;
class EmailSubscriber implements EventSubscriberInterface
{
/**
* SQL Statement to select email template
*/
protected const TEMPLATE_NEW_EVENTS_ONLY = 1;
protected const TEMPLATE_NEW_AND_OLD_EVENTS = 2;
protected const TEMPLATE_OLD_EVENTS_ONLY = 3;
protected const TEMPLATE_NO_EVENTS = 4;
public const FS_TEMPLATES = [
141 => [
'html'=>'customer/141/html.twig',
'text'=>false,
],
];
public function __construct(
private readonly Database $database,
private readonly MailHandler $mailer,
private readonly TemplateLibrary $template
){
}
/**
* Defining required events
* @return \array[][]
*/
public static function getSubscribedEvents():array
{
return [
GrapperProcessEvent::EVENT_RENDER => [
[
'renderTemplate', 1000
]
],
GrapperProcessEvent::EVENT_SEND => [
[
'sendEmail', 1000
]
],
GrapperQueueEvent::EVENT_POST=>[
[
'sendEmailsToCustomer', 1000,
]
],
demoSendEvent::EVENT=>[
'demoSend', 1000
],
testEvent::EVENT=>[
'testSend', 1000
]
];
}
public function testSend(testEvent $event):void{
try{
$mailObj = new Email();
$mailObj->to(base64_decode($event->getEmail()));
$mailObj->subject('Event Scout SMTP Test');
$mailObj->text('Test Email');
$mailObj->from('noreply@rce-event-service.de');
$mailObj->addReplyTo('support@rce.de');
$this->mailer->init($event->getCustomerId());
$this->mailer->getMailer()->send($mailObj);
$event->setResponse(new JsonResponse(['sent'=>true]));
return;
}catch(ErrorException|BaseException|Error $ex){
$event->setResponse(new JsonResponse(['sent'=>false,'reason'=>'Bitte prüfen Sie ihre SMTP-Zugangsdaten!', 'debug' => $ex->getMessage()]));
return;
}
}
/**
* @throws TransportExceptionInterface
* @throws RuntimeError
* @throws BaseException
* @throws LoaderError
* @throws SyntaxError
*/
public function demoSend(demoSendEvent $event):void{
$stmt = $this->database->getConnection()->prepare(acount::GET_SPECIFIC_GRAPPER_CUSTOMER);
$stmt->bindValue(1,$event->getCustomerId());
$resultSet = $stmt->executeQuery();
$customer = $resultSet->fetchAssociative();
if(empty($event->getAdrId())){
$sql = grapperEmailTemplate::GET_TEMPLATE_ACCOUNT;
$stmt = $this->database->getConnection()->prepare($sql);
$stmt->bindValue(1, $event->getCustomerId());
}else{
$sql = grapperEmailTemplate::GET_TEMPLATE;
$stmt = $this->database->getConnection()->prepare($sql);
$stmt->bindValue(1, $event->getCustomerId());
$stmt->bindValue(2, $event->getAdrId());
}
$resultSet = $stmt->executeQuery();
$template = $resultSet->fetchAssociative();
if(empty($event->getAdrId())){
$row = [
'adrid'=>42,
'adrname'=>'test eintrag',
'adrstreet'=>'test straße 1',
'adrcity'=>'test stadt',
'extra1'=>'test',
'extra2'=>'test',
'extra3'=>'test',
'extra4'=>'test',
];
}else{
$sql = eadr::SELECT_ADDRESSE;
$stmt = $this->database->getConnection()->prepare($sql);
$stmt->bindValue(1, $event->getAdrId());
$resultSet = $stmt->executeQuery();
$row = $resultSet->fetchAllAssociative()[0];
}
if(empty($template)){
$event->setResponse(new JsonResponse(['sent'=>false,'reason'=>'Template existiert nicht']));
return;
}
$link = 'https://events.rceevent.de/region/?eintragen';
if(!empty($customer['grapper_meldemodul_link'])){
$link = $customer['grapper_meldemodul_link'];
}
$visibleLink = $link;
$subStmt = $this->database->getConnection()->prepare(emain::GET_REACENT_EVENTS);
$subStmt->bindValue(1, $event->getCustomerId());
$subStmt->bindValue(2, $event->getAdrId());
$subStmt->bindValue(3, $event->getAdrId());
$subStmt->bindValue(4, $event->getAdrId());
$subResultSet = $subStmt->executeQuery();
$events = $subResultSet->fetchAllAssociative();
$resultEvents = [];
if(count($events)>0){
foreach($events as $item){
$resultEvents[] = [
'name' => $item['ename'],
'desc' => $item['edesc'],
'date' => $item['edate'],
'dateTo' => $item['edateto'],
'start' => $item['etimestart'],
'end' => $item['etimeend'],
'hash' => $item['hashid'],
'seolink' => sprintf(Helper::generateSeoUrl($item['ename'], $row['adrcity'], $item['hashid']), $customer['grapper_domain']),
'link' => 'http link zur veranstaltung',
];
}
}
$replaceSet = [
'adressid' => $row['adrid'],
'name' => $row['adrname'],
'street' => $row['adrstreet'],
'city' => $row['adrcity'],
'extra1' => $row['extra1'],
'extra2' => $row['extra2'],
'extra3' => $row['extra3'],
'extra4' => $row['extra4'],
'teamname' => $customer['Name'],
'teamvorname' => $customer['Vorname'],
'teamfirma' => $customer['Firma'],
'teamstrasse' => $customer['Strasse'],
'teamplz' => $customer['Plz'],
'teamort' => $customer['Ort'],
'teamland' => $customer['Land'],
'sender' => $customer['grapper_smtp_self_receive'],
'link' => $link,
'visibleLink' => $visibleLink,
'linkUnsubscribe' => 'https://rce-event.de/modules/meldung/optout.php?id='.$row['adrid'],
'events' => $resultEvents,
'eventCount' => count($resultEvents),
];
$subject = $customer['grapper_betreff'];
if(!empty($template['grapper_betreff'])){
$subject = $template['grapper_betreff'];
}
$loader = new ArrayLoader(
[
'html.twig'=>str_replace(
[
'#sender#', '#teamland#', '#teamort#', '#teamplz#', '#teamstrasse#', '#teamfirma#', '#teamvorname#', '#teamname#', '#name#','#street#','#city#', '#extra1', 'extra2', 'extra2', 'extra4',
],
[
'{{ sender}}', '{{ teamland}}', '{{ teamort}}', '{{ teamplz}}', '{{ teamstrasse}}', '{{ teamfirma}}', '{{ teamvorname}}', '{{ teamname}}', '{{name}}','{{street}}','{{city}}','{{extra1}}','{{extra2}}','{{extra3}}','{{extra4}}',
],
(empty($template['html'])?'':$template['html'])
),
'text.twig'=>str_replace(
[
'#name#','#street#','#city#', '#extra1', 'extra2', 'extra2', 'extra4',
],
[
'{{name}}','{{street}}','{{city}}','{{extra1}}','{{extra2}}','{{extra3}}','{{extra4}}',
],
(empty($template['text'])?'':$template['text'])
),
]
);
$twig = new Environment($loader, [
'cache'=>__DIR__.'/../../var/twig',
]);
$text = str_replace('&', '&', $twig->render('text.twig', $replaceSet));
$html = str_replace('&', '&', $twig->render('html.twig', $replaceSet));
$mailObj = new Email();
$mailObj->to(base64_decode($event->getEmail()));
$mailObj->subject($subject);
if(!empty($text)){
$mailObj->text($text);
}else{
$mailObj->text('leer');
}
if(!empty($html)){
$mailObj->html($html);
}
$mailObj->from('noreply@rce-event-service.de');
$mailObj->addReplyTo('support@rce.de');
try{
$this->mailer->init($event->getCustomerId());
$this->mailer->getMailer()->send($mailObj);
$event->setResponse(new JsonResponse(['sent'=>true]));
return;
}catch(Exception $ex){
$event->setResponse(new JsonResponse(['sent'=>false,'reason'=>'Bitte prüfen Sie ihre SMTP-Zugangsdaten!', 'debug' => $ex->getMessage()]));
return;
}
$event->setResponse(JsonResponse(['sent'=>false,'reason'=>'Unbekannter Fehler. Bitte kontaktieren Sie den Support', 'debug' => $ex->getMessage()]));
}
/**
* render text and html template
* @param \App\Library\Event\GrapperEvent $event
* @return void
* @throws BaseException
* @throws LoaderError
* @throws RuntimeError
* @throws SyntaxError
*/
public function renderTemplate(GrapperProcessEvent $event):void
{
$event->addVerboseOutput('Parsing Templates');
$template = null;
$event->addVerboseOutput('Customer: '.$event->getAcount()->getId().' Address ID: '.$event->getAddress()->getId());
$this->template->reset();
$this->template->prepareTemplate($event);
$this->template->prepareTwig();
$link = 'https://events.rceevent.de/region/?eintragen';
if(!empty($event->getAcount()->getMeldeModulLink())){
$link = $event->getAcount()->getMeldeModulLink();
}
$visibleLink = $link;
if(!strpos($link, '?')!==false){
$link .= '?';
}else{
$link .= '&';
}
$link .= 'gid='.(int)$event->getAddress()->getId();
//var_dump($rowResult);
$subStmt = $this->database->getConnection()->prepare(emain::GET_REACENT_EVENTS);
$subStmt->bindValue(1, $event->getAcount()->getId());
$subStmt->bindValue(2, $event->getAddress()->getId());
$subStmt->bindValue(3, $event->getAddress()->getId());
$subStmt->bindValue(4, $event->getAddress()->getEmail());
$subResultSet = $subStmt->executeQuery();
$events = $subResultSet->fetchAllAssociative();
$resultEvents = [];
$eventMode = 0;
$n = 0;
if(count($events)>0){
foreach($events as $item){
$resultEvents[] = [
'active' => ($item['eonline']==='enable,free'?1:0),
'name' => (strlen($item['ename']) > 35?substr($item['ename'], 0,35).'...':$item['ename']),
'fullname' => $item['ename'],
'desc' => $item['edesc'],
'date' => $item['edate'],
'dateTo' => $item['edateto'],
'start' => $item['etimestart'],
'end' => $item['etimeend'],
'hash' => $item['hashid'],
'city' => (!empty($item['adrcity']) && $item['adrcity']!='-' && $item['adrcity']!=' '?$item['adrcity']:$item['ecity']),
'location' => (!empty($item['adrname'])?$item['adrname']:$item['elocation']),
'street' => (!empty($item['adrstreet'])?$item['adrstreet']:$item['estreet']),
'adrzip' => (!empty($item['adrzip'])?$item['adrzip']:$item['ezip']),
'country' => (!empty($item['adrland'])?$item['adrland']:$item['eland']),
'old' => 0,
'seolink' => sprintf(Helper::generateSeoUrl($item['ename'], $item['adrcity'], $item['hashid']), $event->getAcount()->getDomain()),
'link' => 'http link zur veranstaltung',
];
$n++;
}
}
$i=0;
$o=0;
unset($events, $item);
if(count($resultEvents) < 4){
$subStmt = $this->database->getConnection()->prepare(emain::GET_ALL_EVENTS);
$subStmt->bindValue(1, $event->getAcount()->getId());
$subStmt->bindValue(2, $event->getAddress()->getId());
$subStmt->bindValue(3, $event->getAddress()->getId());
$subStmt->bindValue(4, $event->getAddress()->getEmail());
$datemin = new DateTime();
$dateDiff = new DateInterval('P4Y');
$datemin->sub($dateDiff);
$subStmt->bindValue(5, $datemin->format('Y.m.d H:i:s'));
$subResultSet = $subStmt->executeQuery();
$events = $subResultSet->fetchAllAssociative();
$i = count($resultEvents);
$o = 0;
if(count($events)>0){
foreach($events as $item){
if($i>5){
continue;
}
$resultEvents[] = [
'active' => 0,
'name' => (strlen($item['ename']) > 35?substr($item['ename'], 0,35).'...':$item['ename']),
'fullname' => $item['ename'],
'desc' => $item['edesc'],
'date' => $item['edate'],
'dateTo' => $item['edateto'],
'start' => $item['etimestart'],
'end' => $item['etimeend'],
'hash' => $item['hashid'],
'city' => (!empty($item['adrcity']) && $item['adrcity']!='-' && $item['adrcity']!=' '?$item['adrcity']:$item['ecity']),
'location' => (!empty($item['adrname'])?$item['adrname']:$item['elocation']),
'street' => (!empty($item['adrstreet'])?$item['adrstreet']:$item['estreet']),
'adrzip' => (!empty($item['adrzip'])?$item['adrzip']:$item['ezip']),
'country' => (!empty($item['adrland'])?$item['adrland']:$item['eland']),
'old' => 1,
'seolink' => 'false',
'link' => 'http link zur veranstaltung',
];
$i++;
$o++;
}
}
}
if($n > 0 && $o < 1){
$eventMode = self::TEMPLATE_NEW_EVENTS_ONLY;
}
if($n > 0 && $o > 0){
$eventMode = self::TEMPLATE_NEW_AND_OLD_EVENTS;
}
if($n < 1 && $o > 0){
$eventMode = self::TEMPLATE_OLD_EVENTS_ONLY;
}
if($n < 1 && $o < 1){
$eventMode = self::TEMPLATE_NO_EVENTS;
}
unset($events, $item);
if(count($resultEvents) < 1){
$eventMode = self::TEMPLATE_NO_EVENTS;
}
$replaceSet = [
'adressid' => $event->getAddress()->getId(),
'name' => $event->getAddress()->getName(),
'street' => $event->getAddress()->getStreet(),
'city' => $event->getAddress()->getCity(),
'extra1' => $event->getAddress()->getExtra1(),
'extra2' => $event->getAddress()->getExtra2(),
'extra3' => $event->getAddress()->getExtra3(),
'extra4' => $event->getAddress()->getExtra4(),
'email' => $event->getAddress()->getEmail(),
'eventMode' => $eventMode,
'teamname' => $event->getAcount()->getName(),
'teamvorname' => $event->getAcount()->getFirstName(),
'teamfirma' => $event->getAcount()->getCompany(),
'teamstrasse' => $event->getAcount()->getStreet(),
'teamplz' => $event->getAcount()->getZipCode(),
'teamort' => $event->getAcount()->getCity(),
'teamland' => $event->getAcount()->getCountry(),
'sender' => $event->getAcount()->getSmtpSelfReceive(),
'link' => $link,
'visibleLink' => $visibleLink,
'linkUnsubscribe' => 'https://rce-event.de/modules/meldung/optout.php?id='.$event->getAddress()->getId(),
'events' => $resultEvents,
'eventCount' => count($resultEvents),
];
$event->addVerboseOutput('Mail Mode:'.$eventMode);
$subject = $this->template->getTemplate()->getSubject();
if(!empty($subject)){
$subject = $event->getAcount()->getBetreff();
}
$this->template->render($replaceSet, $event, $subject);
}
/**
* @param GrapperProcessEvent $event
* @return void
* @throws BaseException
*/
public function sendEmail(GrapperProcessEvent $event):void
{
$event->addVerboseOutput('sending Email');
$this->mailer->initMailer($this->mailer->getDsn($event));
if(
!$event->getTemplate()->containsKey('subject')
||
empty($event->getTemplate()->get('subject'))
){
$event->stopPropagation();
$event->addVerboseOutput('html templateis empty for '.$event->getAddressId());
return;
}
$template = $event->getTemplate();
$adrid = $event->getAddress()->getId();
$event->addVerboseOutput('Customer: '.$event->getAcount()->getId().' Address ID: '.$adrid);
if(!filter_var($event->getAddress()->getEmail(), FILTER_VALIDATE_EMAIL)){
//disable Address as it fails
$stmt = $this->database->getConnection()->prepare(eadr::DISABLE_EMAIL_SENDING_DUE_TO_ERROR);
$stmt->bindValue(1,$event->getCustomerId());
$stmt->bindValue(2,$event->getAddressId());
$stmt->executeQuery();
$event->addVerboseOutput('Due to an error within the email Adress the Addressid '.$event->getAddressId(). ' was disabled');
$event->stopPropagation();
return;
}
$blacklist = $this->database->getData(blacklistEmail::class, blacklistEmail::CHECK_EMAIL_BLACKLIST, [$event->getAddress()->getEmail()]);
if(!empty($blacklist)){
$stmt = $this->database->getConnection()->prepare(eadr::DISABLE_EMAIL_SENDING_DUE_TO_ERROR);
$stmt->bindValue(1,$event->getCustomerId());
$stmt->bindValue(2,$event->getAddressId());
$stmt->executeQuery();
$event->addVerboseOutput('The Address is Blacklisted '.$event->getAddressId(). ' so it was disabled');
$event->stopPropagation();
$event->addVerboseOutput('email address is blacklisted'.$event->getAddress()->getEmail());
return;
}
try{
//blacklist scann end
$email = new Email();
$receiver = [];
if(MailHandler::DEBUG_MODE > 0){
$i=0;
foreach(MailHandler::DEBUG_EMAILS as $row){
if($i===0){
$receiver[] = $row;
$email->to($row);
$i++;
}else{
$receiver[] = $row;
$email->addTo($row);
}
}
}else{
$receiver[] = $event->getAddress()->getEmail();
$email->to($event->getAddress()->getEmail());
}
$email->subject($event->getTemplate()->get('subject'));
if(!empty($event->getTemplate()->get('html'))){
$email->html($event->getTemplate()->get('html'));
}
if(!empty($event->getTemplate()->get('text'))){
$email->text($event->getTemplate()->get('text'));
}
if(!empty($event->getAcount()->getSmtpSelfReceive())){
$email->addBcc($event->getAcount()->getSmtpSelfReceive());
}
if(MailHandler::FREE_MAILER_ENABLED && $event->getAcount()->getLizenz()->isFreeMailer()){
$email->from(MailHandler::FREE_MAILER_USER);
}else{
$email->from($event->getAcount()->getSender());
}
if(!empty($event->getAcount()->getReplyTo())){
$email->addReplyTo($event->getAcount()->getReplyTo());
}else{
$email->addReplyTo($event->getAcount()->getSender());
}
if(!empty($event->getAcount()->getSmtpSelfReceive())){
$email->bcc($event->getAcount()->getSmtpSelfReceive());
}
}catch(RfcComplianceException $ex){
$event->addVerboseOutput($ex->getMessage());
}
$event->addVerboseOutput('email is sent');
if(MailHandler::DEBUG_SEND > 0){
$event->addVerboseOutput($event->getAddress()->getEmail());
}else{
$event->addVerboseOutput('email sent');
$this->mailer->getMailer()->send($email);
}
$sql = sprintf(grapperMailLog::LOG_MAIL_SENT, $event->getAddress()->getEmail(), (int)$event->getAcount()->getId());
$stmt = $this->database->getConnection()->prepare($sql);
$stmt->executeQuery();
$event->setSent(true);
if($event->getAcount()->getSendDelay() > 0){
//sleep($event->getAcount()->getSendDelay());
}
unset($transport, $mailer, $email, $dsn, $stmt);
}
/**
* @throws SyntaxError
* @throws RuntimeError
* @throws LoaderError
* @throws BaseException
*/
public function sendEmailsToCustomer(GrapperQueueEvent $event):void{
$this->mailer->initMailer($this->mailer->initStatisticSender($event));
$email = new Email();
if(MailHandler::DEBUG_MODE > 0){
$i=0;
foreach(MailHandler::DEBUG_EMAILS as $row){
$email->addTo($row);
}
}else{
$email->addTo($event->getAcount()->getEmail());
}
if(!empty(MailHandler::DEFAULT_STATISTIC_RECEIVER))
{
$email->addTo(MailHandler::DEFAULT_STATISTIC_RECEIVER);
}
$email->from(MailHandler::STATISTICS_MAILER_USER);
$email->addReplyTo(MailHandler::DEFAULT_STATISTIC_SENDER);
$email->subject(MailHandler::STATISTICS_SUBJECT);
$loader = new ArrayLoader(
[
'html.twig'=>file_get_contents(__DIR__.'/../../../templates/email.statistics.html.twig'),
]
);
$twig = new Environment($loader, [
'cache'=>__DIR__.'/../../../var/twig',
]);
$stmt = $this->database->getConnection()->prepare(grapperMailLog::LOG_MAIL_SENT_SUCCESSFULL);
$stmt->bindValue(1, $event->getStartTime()->format('y.m.d H:i:s'));
$interval = new DateInterval('PT30S');
$currentTime = (new DateTime())->add($interval);
$stmt->bindValue(2, $currentTime->format('y.m.d H:i:s'));
$result = $stmt->executeQuery();
$resultArray = $result->fetchAssociative();
$parameters = [
'sent' => $event->getAddresses()->toArray(),
'total' => $event->getAddresses()->count(),
'customer' => $event->getAcount(),
'sentCounter'=>$resultArray['cnt'],
];
$html = $twig->render('html.twig', $parameters);
$email->html($html);
try{
if(MailHandler::DEBUG_MODE === 0)
{
$this->mailer->send($email);
}else{
dump($parameters);
}
}catch (TransportExceptionInterface $ex){
$event->addVerboseOutput($ex->getMessage());
}catch(Exception $ex){
$event->addVerboseOutput($ex->getMessage());
}
}
}