From b45bbe63f5bfacb6188a0e9eb8d181bb27ea8d03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Gangloff?= Date: Sun, 21 Jul 2024 13:59:00 +0200 Subject: [PATCH] feat: send an email when a domain has been modified --- .env | 1 + config/services.yaml | 3 + .../SendNotifWatchListTriggerHandler.php | 62 +++++++++++++++++-- .../SendNotifWatchListTriggerSchedule.php | 2 +- templates/emails/domain_updated.html.twig | 14 +++++ .../emails/errors/domain_update.html.twig | 17 +++++ 6 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 templates/emails/domain_updated.html.twig create mode 100644 templates/emails/errors/domain_update.html.twig diff --git a/.env b/.env index 61285c3..3cfd70d 100644 --- a/.env +++ b/.env @@ -38,6 +38,7 @@ MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0 ###> symfony/mailer ### # MAILER_DSN=null://null +MAILER_SENDER_EMAIL=notifications@example.com ###< symfony/mailer ### ###> nelmio/cors-bundle ### diff --git a/config/services.yaml b/config/services.yaml index 2d6a76f..b11a78a 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -4,12 +4,15 @@ # Put parameters here that don't need to change on each machine where the app is deployed # https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration parameters: + mailer_sender_email: '%env(MAILER_SENDER_EMAIL)%' services: # default configuration for services in *this* file _defaults: autowire: true # Automatically injects dependencies in your services. autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. + bind: + $mailerSenderEmail: '%mailer_sender_email%' # makes classes in src/ available to be used as services # this creates a service per class whose id is the fully-qualified class name diff --git a/src/MessageHandler/SendNotifWatchListTriggerHandler.php b/src/MessageHandler/SendNotifWatchListTriggerHandler.php index 289d1c9..cb69555 100644 --- a/src/MessageHandler/SendNotifWatchListTriggerHandler.php +++ b/src/MessageHandler/SendNotifWatchListTriggerHandler.php @@ -5,6 +5,7 @@ namespace App\MessageHandler; use App\Config\TriggerAction; use App\Entity\Domain; use App\Entity\DomainEvent; +use App\Entity\User; use App\Entity\WatchList; use App\Entity\WatchListTrigger; use App\Message\SendNotifWatchListTrigger; @@ -12,22 +13,29 @@ use App\Repository\WatchListRepository; use App\Service\RDAPService; use DateTimeImmutable; use Exception; +use Symfony\Bridge\Twig\Mime\TemplatedEmail; +use Symfony\Component\Mailer\Exception\TransportExceptionInterface; +use Symfony\Component\Mailer\MailerInterface; use Symfony\Component\Messenger\Attribute\AsMessageHandler; +use Symfony\Component\Mime\Email; use Throwable; #[AsMessageHandler] -final class SendNotifWatchListTriggerHandler +readonly final class SendNotifWatchListTriggerHandler { public function __construct( private WatchListRepository $watchListRepository, - private RDAPService $RDAPService + private RDAPService $RDAPService, + private MailerInterface $mailer, + private string $mailerSenderEmail ) { } /** * @throws Exception + * @throws TransportExceptionInterface */ public function __invoke(SendNotifWatchListTrigger $message): void { @@ -40,24 +48,26 @@ final class SendNotifWatchListTriggerHandler ->diff(new DateTimeImmutable('now'))->days >= 7) as $domain ) { $updatedAt = $domain->getUpdatedAt(); + try { $domain = $this->RDAPService->registerDomain($domain->getLdhName()); } catch (Throwable) { - + $this->sendEmailDomainUpdateError($domain, $watchList->getUser()); + continue; } + /** @var DomainEvent $event */ foreach ($domain->getEvents()->filter(fn($event) => $updatedAt < $event->getDate()) as $event) { $watchListTriggers = $watchList->getWatchListTriggers() - ->filter(fn($trigger) => $trigger->getAction() === $event->getAction()); + ->filter(fn($trigger) => $trigger->getEvent() === $event->getAction()); /** @var WatchListTrigger $watchListTrigger */ foreach ($watchListTriggers->getIterator() as $watchListTrigger) { switch ($watchListTrigger->getAction()) { case TriggerAction::SendEmail: - //TODO: To be implemented - throw new Exception('To be implemented'); + $this->sendEmailDomainUpdated($event, $watchList->getUser()); } } } @@ -65,4 +75,44 @@ final class SendNotifWatchListTriggerHandler } } + + /** + * @throws TransportExceptionInterface + */ + public function sendEmailDomainUpdateError(Domain $domain, User $user): Email + { + $email = (new TemplatedEmail()) + ->from($this->mailerSenderEmail) + ->to($user->getEmail()) + ->subject('An error occurred while updating a domain name') + ->htmlTemplate('emails/errors/domain_update.html.twig') + ->locale('en') + ->context([ + "domain" => $domain + ]); + + $this->mailer->send($email); + return $email; + } + + /** + * @throws TransportExceptionInterface + */ + public function sendEmailDomainUpdated(DomainEvent $domainEvent, User $user): Email + { + $email = (new TemplatedEmail()) + ->from($this->mailerSenderEmail) + ->to($user->getEmail()) + ->priority(Email::PRIORITY_HIGHEST) + ->subject('A domain name has been changed') + ->htmlTemplate('emails/domain_updated.html.twig') + ->locale('en') + ->context([ + "event" => $domainEvent + ]); + + $this->mailer->send($email); + return $email; + } + } diff --git a/src/Scheduler/SendNotifWatchListTriggerSchedule.php b/src/Scheduler/SendNotifWatchListTriggerSchedule.php index 7431f16..c8df890 100644 --- a/src/Scheduler/SendNotifWatchListTriggerSchedule.php +++ b/src/Scheduler/SendNotifWatchListTriggerSchedule.php @@ -21,7 +21,7 @@ final readonly class SendNotifWatchListTriggerSchedule implements ScheduleProvid { return (new Schedule()) ->add( - RecurringMessage::every('1 week', new SendNotifWatchListTrigger()), + RecurringMessage::every('10 seconds', new SendNotifWatchListTrigger()), ) ->stateful($this->cache) ; diff --git a/templates/emails/domain_updated.html.twig b/templates/emails/domain_updated.html.twig new file mode 100644 index 0000000..006c28c --- /dev/null +++ b/templates/emails/domain_updated.html.twig @@ -0,0 +1,14 @@ +

+ Hello,
+
+ We are pleased to inform you that a new action has been detected on a domain name in your watchlist.
+ Domain name : {{ event.domain.ldhName }}
+ Action : {{ event.action.value }}
+ Effective Date : {{ event.date | date("c") }}
+
+
+ Thank you for your understanding,
+ Sincerely
+
+ Domain Watchdog +

\ No newline at end of file diff --git a/templates/emails/errors/domain_update.html.twig b/templates/emails/errors/domain_update.html.twig new file mode 100644 index 0000000..860663a --- /dev/null +++ b/templates/emails/errors/domain_update.html.twig @@ -0,0 +1,17 @@ +

+ Hello,
+
+ We would like to inform you that an error occurred while updating the information for the following domain name. +
+ Domain name : {{ domain.ldhName }}
+
+ Here are some possible explanations:
+ * It is likely that the domain will be available for registration again.
+ * A temporary outage affects the provision of domain name information.
+
+
+ Thank you for your understanding,
+ Sincerely
+
+ Domain Watchdog +

\ No newline at end of file