Repository: MTES-MCT/histologe
Pull request #3777: [BO - Command renvoi FailedEmail] Améliorer
Author: login: numew
Created: 2025-03-03T15:26:23Z | Merged: 2025-03-04T14:45:58Z

## Ticket

#3771

## Description
- Ajout de la gestion du champ `isRecipientVisible`  dans FailedEmail afin d'être iso avec l'envoie classique 
- Suppression des email en erreur avec +de 900 tentative de renvoie (faisant suite au bug sur l'auto affectation)

## Pré-requis
make execute-migration name=Version20250303140936 direction=up

## Tests
- [ ] Provoquer volontairement une erreur lors de l'envoie d'email
- [ ] Ajouter un suivie (partagé a l'utilisateur) sur un signalement ayant plusieurs affectations
- [ ] Lancer la commande `app:retry-failed-emails` et s'assurer que les destinaire to et bcc sont comme attendus



Diff:
diff --git a/migrations/Version20250303140936.php b/migrations/Version20250303140936.php
new file mode 100644
index 0000000000..11590ff7b5
--- /dev/null
+++ b/migrations/Version20250303140936.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DoctrineMigrations;
+
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\Migrations\AbstractMigration;
+
+final class Version20250303140936 extends AbstractMigration
+{
+    public function getDescription(): string
+    {
+        return 'Add new columns to failed_email table';
+    }
+
+    public function up(Schema $schema): void
+    {
+        $this->addSql('DELETE FROM failed_email WHERE retry_count > 900 AND is_resend_successful = 0');
+        $this->addSql('ALTER TABLE failed_email ADD is_recipient_visible TINYINT(1) NOT NULL');
+        $this->addSql('UPDATE failed_email SET is_recipient_visible = 1');
+    }
+
+    public function down(Schema $schema): void
+    {
+        $this->addSql('ALTER TABLE failed_email DROP is_recipient_visible');
+    }
+}
diff --git a/src/Command/RetryFailedEmailsCommand.php b/src/Command/RetryFailedEmailsCommand.php
index 602f087f93..6f4b5de672 100644
--- a/src/Command/RetryFailedEmailsCommand.php
+++ b/src/Command/RetryFailedEmailsCommand.php
@@ -56,9 +56,16 @@ protected function execute(InputInterface $input, OutputInterface $output): int
                 )
             ;
 
+            if (!$failedEmail->isRecipientVisible() && isset($failedEmail->getReplyTo()[0])) {
+                $emailMessage->addTo($emailMessage->getReplyTo()[0]);
+            }
             foreach ($failedEmail->getToEmail() as $toEmail) {
-                if ('NC' !== $toEmail) {
-                    $toEmail && $emailMessage->addTo($toEmail);
+                if ($toEmail && 'NC' !== $toEmail) {
+                    if ($failedEmail->isRecipientVisible()) {
+                        $emailMessage->addTo($toEmail);
+                    } else {
+                        $emailMessage->addBcc($toEmail);
+                    }
                 }
             }
             if (
diff --git a/src/Entity/FailedEmail.php b/src/Entity/FailedEmail.php
index 4840a1ffc7..be2614da94 100644
--- a/src/Entity/FailedEmail.php
+++ b/src/Entity/FailedEmail.php
@@ -52,6 +52,9 @@ class FailedEmail
     #[ORM\Column(type: 'datetime_immutable', nullable: true)]
     private ?\DateTimeImmutable $lastAttemptAt;
 
+    #[ORM\Column]
+    private ?bool $isRecipientVisible = null;
+
     public function __construct()
     {
         $this->createdAt = new \DateTimeImmutable();
@@ -224,4 +227,16 @@ public function setLastAttemptAt(?\DateTimeImmutable $lastAttemptAt): static
 
         return $this;
     }
+
+    public function isRecipientVisible(): ?bool
+    {
+        return $this->isRecipientVisible;
+    }
+
+    public function setIsRecipientVisible(bool $isRecipientVisible): static
+    {
+        $this->isRecipientVisible = $isRecipientVisible;
+
+        return $this;
+    }
 }
diff --git a/src/Manager/FailedEmailManager.php b/src/Manager/FailedEmailManager.php
index 1b90a977f4..c330155be3 100644
--- a/src/Manager/FailedEmailManager.php
+++ b/src/Manager/FailedEmailManager.php
@@ -29,6 +29,7 @@ public function create(
             ->setFromEmail($message->getFrom()[0]->getAddress() ?? '')
             ->setFromFullname($message->getFrom()[0]->getName())
             ->setReplyTo($replyTo)
+            ->setIsRecipientVisible($notificationMail->isRecipientVisible())
             ->setSubject($message->getSubject())
             ->setContext($message->getContext())
             ->setNotifyUsager($notifyUsager)


Reviews:
user: login: emilschn
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-04T09:55:57Z
user: login: emilschn
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-04T09:56:03Z
user: login: emilschn
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-04T09:58:13Z
user: login: numew
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-04T13:28:40Z
user: login: numew
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-04T13:28:49Z
user: login: hmeneuvrier
body: Relecture et tests OK
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-04T14:06:12Z

Review comments:
diff_hunk: @@ -56,9 +56,16 @@ protected function execute(InputInterface $input, OutputInterface $output): int
                 )
             ;
 
+            if (!$failedEmail->isRecipientVisible() && isset($failedEmail->getReplyTo()[0])) {
+                $emailMessage->addTo($emailMessage->getReplyTo()[0]);
+            }
             foreach ($failedEmail->getToEmail() as $toEmail) {
                 if ('NC' !== $toEmail) {
-                    $toEmail && $emailMessage->addTo($toEmail);
+                    if ($failedEmail->isRecipientVisible()) {
+                        $toEmail && $emailMessage->addTo($toEmail);
path: src/Command/RetryFailedEmailsCommand.php
user: login: emilschn
body: tu voulais pas juste tester `toEmail` ligne 63, vu que tu le fais déjà ? :)
created_at: 2025-03-04T09:55:57Z
author_association: COLLABORATOR
diff_hunk: @@ -56,9 +56,16 @@ protected function execute(InputInterface $input, OutputInterface $output): int
                 )
             ;
 
+            if (!$failedEmail->isRecipientVisible() && isset($failedEmail->getReplyTo()[0])) {
+                $emailMessage->addTo($emailMessage->getReplyTo()[0]);
+            }
             foreach ($failedEmail->getToEmail() as $toEmail) {
                 if ('NC' !== $toEmail) {
-                    $toEmail && $emailMessage->addTo($toEmail);
+                    if ($failedEmail->isRecipientVisible()) {
+                        $toEmail && $emailMessage->addTo($toEmail);
+                    } else {
+                        $toEmail && $emailMessage->addBcc($toEmail);
path: src/Command/RetryFailedEmailsCommand.php
user: login: emilschn
body: idem
created_at: 2025-03-04T09:56:03Z
author_association: COLLABORATOR
diff_hunk: @@ -23,12 +23,14 @@ public function create(
         string $replyTo,
         bool $notifyUsager,
     ): FailedEmail {
+        $notificationMail->isRecipientVisible();
path: src/Manager/FailedEmailManager.php
user: login: emilschn
body: c'est utile ça ?
created_at: 2025-03-04T09:58:13Z
author_association: COLLABORATOR
diff_hunk: @@ -56,9 +56,16 @@ protected function execute(InputInterface $input, OutputInterface $output): int
                 )
             ;
 
+            if (!$failedEmail->isRecipientVisible() && isset($failedEmail->getReplyTo()[0])) {
+                $emailMessage->addTo($emailMessage->getReplyTo()[0]);
+            }
             foreach ($failedEmail->getToEmail() as $toEmail) {
                 if ('NC' !== $toEmail) {
-                    $toEmail && $emailMessage->addTo($toEmail);
+                    if ($failedEmail->isRecipientVisible()) {
+                        $toEmail && $emailMessage->addTo($toEmail);
path: src/Command/RetryFailedEmailsCommand.php
user: login: numew
body: ok
created_at: 2025-03-04T13:28:39Z
author_association: COLLABORATOR
diff_hunk: @@ -23,12 +23,14 @@ public function create(
         string $replyTo,
         bool $notifyUsager,
     ): FailedEmail {
+        $notificationMail->isRecipientVisible();
path: src/Manager/FailedEmailManager.php
user: login: numew
body: Non, c'est corrigé
created_at: 2025-03-04T13:28:49Z
author_association: COLLABORATOR

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-03-04T13:29:26Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=MTES-MCT_histologe&pullRequest=3777) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=MTES-MCT_histologe&pullRequest=3777&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=MTES-MCT_histologe&pullRequest=3777&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=MTES-MCT_histologe&pullRequest=3777&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=MTES-MCT_histologe&pullRequest=3777&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=MTES-MCT_histologe&pullRequest=3777&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=MTES-MCT_histologe&pullRequest=3777)


author_association: NONE