From ed03bb79d664989f825ac9c4aa3eb5bc3a7cf94d Mon Sep 17 00:00:00 2001 From: Flo Date: Sat, 14 Sep 2024 13:50:28 +0000 Subject: [PATCH] changes to mail --- .env.example | 3 +- config/autoload/mail.global.php | 3 +- .../business/Version20240911191301.php | 40 +++++++ src/ApiDomain/Console/config/console.php | 2 + .../Console/config/service_manager.php | 2 + .../src/Command/InitializeDataCommand.php | 1 + .../Console/src/Command/RbacUpdateCommand.php | 1 + .../Console/src/Command/SendMailsCommand.php | 43 +++++++ .../Health/src/Handler/HealthHandler.php | 6 +- src/DataDomain/Business/src/Entity/Mail.php | 112 ++++++++++++++++++ .../src/Repository/MailRepository.php | 10 ++ .../RegisterUser/Step/SendMailStep.php | 6 +- .../ForgotPasswordCommandHandler.php | 4 +- .../Mail/src/Service/MailService.php | 63 +++++++++- 14 files changed, 279 insertions(+), 17 deletions(-) create mode 100644 data/migrations/business/Version20240911191301.php create mode 100644 src/ApiDomain/Console/src/Command/SendMailsCommand.php create mode 100644 src/DataDomain/Business/src/Entity/Mail.php create mode 100644 src/DataDomain/Business/src/Repository/MailRepository.php diff --git a/.env.example b/.env.example index 8740ee5..ddcddce 100644 --- a/.env.example +++ b/.env.example @@ -20,7 +20,8 @@ INIT_USER_PASSWORD=password INIT_USER_MAIL=admin@test.com # Mail -MAIL_DEFAULT_SENDER=info@bee.local +MAIL_DEFAULT_SENDER=beekeeper@stack-up.de +MAIL_DEFAULT_SENDER_NAME=Beekeeper SMTP_USERNAME=smtp@stack-up.de SMTP_PASSWORD= SMTP_HOST= #srv-mail-01.lab.jonasf.de diff --git a/config/autoload/mail.global.php b/config/autoload/mail.global.php index b7b8ca3..a5b855f 100644 --- a/config/autoload/mail.global.php +++ b/config/autoload/mail.global.php @@ -3,7 +3,8 @@ return [ 'mail' => [ 'default' => [ - 'sender' => $_ENV['MAIL_DEFAULT_SENDER'] + 'sender' => $_ENV['MAIL_DEFAULT_SENDER'], + 'senderName' => $_ENV['MAIL_DEFAULT_SENDER_NAME'] ], 'smtp-server' => [ 'host' => $_ENV['SMTP_HOST'], diff --git a/data/migrations/business/Version20240911191301.php b/data/migrations/business/Version20240911191301.php new file mode 100644 index 0000000..976be49 --- /dev/null +++ b/data/migrations/business/Version20240911191301.php @@ -0,0 +1,40 @@ +addSql($sql); + } + + public function down(Schema $schema): void + { + $this->addSql("DROP TABLE mail;"); + } +} diff --git a/src/ApiDomain/Console/config/console.php b/src/ApiDomain/Console/config/console.php index 3f1b534..27ff5d7 100644 --- a/src/ApiDomain/Console/config/console.php +++ b/src/ApiDomain/Console/config/console.php @@ -2,10 +2,12 @@ use Bee\API\Console\Command\InitializeDataCommand; use Bee\API\Console\Command\RbacUpdateCommand; +use Bee\API\Console\Command\SendMailsCommand; return [ 'commands' => [ InitializeDataCommand::class, RbacUpdateCommand::class, + SendMailsCommand::class, ] ]; diff --git a/src/ApiDomain/Console/config/service_manager.php b/src/ApiDomain/Console/config/service_manager.php index 7b31cad..55d531c 100644 --- a/src/ApiDomain/Console/config/service_manager.php +++ b/src/ApiDomain/Console/config/service_manager.php @@ -2,11 +2,13 @@ use Bee\API\Console\Command\InitializeDataCommand; use Bee\API\Console\Command\RbacUpdateCommand; +use Bee\API\Console\Command\SendMailsCommand; use Reinfi\DependencyInjection\Factory\AutoWiringFactory; return [ 'factories' => [ InitializeDataCommand::class => AutoWiringFactory::class, RbacUpdateCommand::class => AutoWiringFactory::class, + SendMailsCommand::class => AutoWiringFactory::class, ], ]; diff --git a/src/ApiDomain/Console/src/Command/InitializeDataCommand.php b/src/ApiDomain/Console/src/Command/InitializeDataCommand.php index 4f7f9cd..a724a42 100644 --- a/src/ApiDomain/Console/src/Command/InitializeDataCommand.php +++ b/src/ApiDomain/Console/src/Command/InitializeDataCommand.php @@ -75,6 +75,7 @@ class InitializeDataCommand extends Command return Command::FAILURE; } + $io->success("Done"); return Command::SUCCESS; } } diff --git a/src/ApiDomain/Console/src/Command/RbacUpdateCommand.php b/src/ApiDomain/Console/src/Command/RbacUpdateCommand.php index f8f6996..c5089df 100644 --- a/src/ApiDomain/Console/src/Command/RbacUpdateCommand.php +++ b/src/ApiDomain/Console/src/Command/RbacUpdateCommand.php @@ -93,6 +93,7 @@ class RbacUpdateCommand extends Command return Command::FAILURE; } + $io->success("Done"); return Command::SUCCESS; } } diff --git a/src/ApiDomain/Console/src/Command/SendMailsCommand.php b/src/ApiDomain/Console/src/Command/SendMailsCommand.php new file mode 100644 index 0000000..8869c8e --- /dev/null +++ b/src/ApiDomain/Console/src/Command/SendMailsCommand.php @@ -0,0 +1,43 @@ +getName()); + } + + protected function execute( + InputInterface $input, + OutputInterface $output + ): int { + $io = new SymfonyStyle($input, $output); + + try { + $this->service->send(); + + } catch (\Throwable $e) { + $io->error($e->getMessage()); + $io->error($e->getTraceAsString()); + $this->logger->error($e->getMessage(), ['exception' => $e]); + return Command::FAILURE; + } + + $io->success("Done"); + return Command::SUCCESS; + } +} diff --git a/src/ApiDomain/External/Health/src/Handler/HealthHandler.php b/src/ApiDomain/External/Health/src/Handler/HealthHandler.php index 76b1361..2b51937 100644 --- a/src/ApiDomain/External/Health/src/Handler/HealthHandler.php +++ b/src/ApiDomain/External/Health/src/Handler/HealthHandler.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Bee\API\External\Health\Handler; +use Bee\Infrastructure\Mail\Service\MailService; use Laminas\Diactoros\Response\JsonResponse; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -11,7 +12,8 @@ use Psr\Http\Server\RequestHandlerInterface; class HealthHandler implements RequestHandlerInterface { - public function __construct() { + public function __construct( + ) { } public function handle(ServerRequestInterface $request): ResponseInterface @@ -19,5 +21,3 @@ class HealthHandler implements RequestHandlerInterface return new JsonResponse("I'm fine. :)"); } } - -?> diff --git a/src/DataDomain/Business/src/Entity/Mail.php b/src/DataDomain/Business/src/Entity/Mail.php new file mode 100644 index 0000000..f5aad21 --- /dev/null +++ b/src/DataDomain/Business/src/Entity/Mail.php @@ -0,0 +1,112 @@ +id = UuidGenerator::generate(); + + $now = new DateTime(); + $this->setCreatedAt($now); + } + + + /** + * @ORM\PrePersist + * @ORM\PreUpdate + */ + public function updateTimestamps(): void { + $now = new DateTime(); + //$this->setUpdatedAt($now); + } + + + public function getId(): UuidInterface { + return $this->id; + } + + public function getTemplate(): string + { + return $this->template; + } + public function setTemplate(string $template): void + { + $this->template = $template; + } + + public function getData(): array + { + return $this->data; + } + public function setData(array $data): void + { + $this->data = $data; + } + + public function getRecipient(): string + { + return $this->recipient; + } + public function setRecipient(string $recipient): void + { + $this->recipient = $recipient; + } + + public function getSender(): ?string + { + return $this->sender; + } + public function setSender(?string $sender): void + { + $this->sender = $sender; + } + + public function getSenderName(): ?string + { + return $this->senderName; + } + public function setSenderName(?string $senderName): void + { + $this->senderName = $senderName; + } + + public function getCreatedAt(): DateTime { + return $this->createdAt; + } + public function setCreatedAt(DateTime $createdAt): void { + $this->createdAt = $createdAt; + } +} diff --git a/src/DataDomain/Business/src/Repository/MailRepository.php b/src/DataDomain/Business/src/Repository/MailRepository.php new file mode 100644 index 0000000..610acc7 --- /dev/null +++ b/src/DataDomain/Business/src/Repository/MailRepository.php @@ -0,0 +1,10 @@ +getCommand(); $registration = $payload->getRegistration(); - $this->mailService->send( + $this->mailService->enqueue( template: 'registration', templateData: [ 'username' => $command->getUsername(), @@ -40,9 +40,7 @@ class SendMailStep implements TaskInterface $registration->getId()->toString() ) ], - recipient: $command->getMail(), - sender: 'beekeeper@stack-up.de', - senderName: "Beekeeper" + recipient: $command->getMail() ); $pipeline->next()($payload, $pipeline); diff --git a/src/HandlingDomain/User/src/Handler/Command/ForgotPassword/ForgotPasswordCommandHandler.php b/src/HandlingDomain/User/src/Handler/Command/ForgotPassword/ForgotPasswordCommandHandler.php index fca5d86..b755aad 100644 --- a/src/HandlingDomain/User/src/Handler/Command/ForgotPassword/ForgotPasswordCommandHandler.php +++ b/src/HandlingDomain/User/src/Handler/Command/ForgotPassword/ForgotPasswordCommandHandler.php @@ -50,7 +50,7 @@ class ForgotPasswordCommandHandler $this->entityManager->persist($passwordToken); $this->entityManager->flush(); - $this->mailService->send( + $this->mailService->enqueue( 'reset-password', templateData: [ 'username' => $user->getUsername(), @@ -61,8 +61,6 @@ class ForgotPasswordCommandHandler ) ], recipient: $mail, - sender: 'beekeeper@stack-up.de', - senderName: 'Beekeeper' ); return new ForgotPasswordCommandResult(); diff --git a/src/Infrastructure/Mail/src/Service/MailService.php b/src/Infrastructure/Mail/src/Service/MailService.php index a2073f9..6329c50 100644 --- a/src/Infrastructure/Mail/src/Service/MailService.php +++ b/src/Infrastructure/Mail/src/Service/MailService.php @@ -4,6 +4,9 @@ declare(strict_types=1); namespace Bee\Infrastructure\Mail\Service; +use Bee\Data\Business\Entity\Mail; +use Bee\Data\Business\Manager\EntityManager; +use Bee\Data\Business\Repository\MailRepository; use Exception; use Latte\Engine; use Nette\Mail\Mailer; @@ -18,18 +21,70 @@ class MailService { private const TEMPLATE_PATH = APP_ROOT . '/data/mails/'; private readonly Engine $engine; + private readonly MailRepository $mailRepository; public function __construct( + private readonly EntityManager $entityManager, private readonly ConfigService $configService, private readonly Logger $logger, ) { $this->engine = new Engine(); + + $this->mailRepository = $this->entityManager->getRepository(Mail::class); + } + + public function enqueue( + string $template, + array $templateData, + string $recipient, + ?string $sender = null, + ?string $senderName = null + ): void { + $mail = new Mail(); + $mail->setTemplate($template); + $mail->setData($templateData); + $mail->setRecipient($recipient); + $mail->setSender($sender); + $mail->setSenderName($senderName); + + $this->entityManager->persist($mail); + $this->entityManager->flush(); + } + + public function send(?int $count = null): void { + $qb = $this->mailRepository->createQueryBuilder('m'); + $qb->orderBy('m.createdAt', 'asc'); + + if ($count !== null) { + $qb->setMaxResults($count); + } + + $mailsToSend = $qb->getQuery()->execute(); + + /** @var Mail $mailToSend */ + foreach ($mailsToSend as $mailToSend) { + + try { + $this->sendMail( + $mailToSend->getTemplate(), + $mailToSend->getData(), + $mailToSend->getRecipient(), + $mailToSend->getSender(), + $mailToSend->getSenderName(), + ); + + $this->entityManager->remove($mailToSend); + } catch (SendMailFailedException $e) { + // log is done withing sendMail + } + $this->entityManager->flush(); + } } /** * @throws SendMailFailedException */ - public function send( + private function sendMail( string $template, array $templateData, string $recipient, @@ -112,9 +167,7 @@ class MailService $defaultConfig = $this->configService->resolve('mail.default'); $from = $sender ?? $defaultConfig['sender'] ?? throw new Exception('Could not determine Sender'); - if ($senderName !== null) { - $from = sprintf('%s <%s>', $senderName, $from); - } - return $from; + $name =$sender ?? $defaultConfig['senderName'] ?? throw new Exception('Could not determine Sender Name'); + return sprintf('%s <%s>', $name, $from); } } \ No newline at end of file