feat(mail) : MailMessageReadController + MailMessageFlagController - POST .../read et .../flag

- POST /api/mail/messages/{id}/read body {read: bool} - synchro IMAP + BDD
- POST /api/mail/messages/{id}/flag body {flagged: bool} - synchro IMAP + BDD
- IMAP-side non bloquant : BDD est mise a jour meme si IMAP fail (resync au prochain cycle)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-20 00:10:06 +02:00
parent 5ce7693343
commit f584ed96fa
2 changed files with 106 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
namespace App\Controller\Mail;
use App\Mail\Exception\MailProviderException;
use App\Mail\MailProviderInterface;
use App\Repository\MailMessageRepository;
use App\Security\MailAccessChecker;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route('/api/mail/messages/{id}/flag', name: 'mail_message_flag', methods: ['POST'], priority: 1, requirements: ['id' => '\d+'])]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
class MailMessageFlagController extends AbstractController
{
public function __construct(
private readonly MailMessageRepository $messageRepository,
private readonly MailProviderInterface $mailProvider,
private readonly EntityManagerInterface $em,
private readonly MailAccessChecker $accessChecker,
) {}
public function __invoke(Request $request, int $id): JsonResponse
{
$this->accessChecker->ensureCanAccessMail($this->getUser());
$message = $this->messageRepository->find($id);
if (null === $message) {
throw new NotFoundHttpException('Message not found');
}
$body = json_decode($request->getContent(), true);
$flagged = (bool) ($body['flagged'] ?? true);
try {
$this->mailProvider->markFlagged($message->getFolder()->getPath(), $message->getUid(), $flagged);
} catch (MailProviderException) {
// Non bloquant
}
$message->setIsFlagged($flagged);
$this->em->flush();
return $this->json(['id' => $message->getId(), 'isFlagged' => $message->isFlagged()]);
}
}

View File

@@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
namespace App\Controller\Mail;
use App\Mail\Exception\MailProviderException;
use App\Mail\MailProviderInterface;
use App\Repository\MailMessageRepository;
use App\Security\MailAccessChecker;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route('/api/mail/messages/{id}/read', name: 'mail_message_read', methods: ['POST'], priority: 1, requirements: ['id' => '\d+'])]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
class MailMessageReadController extends AbstractController
{
public function __construct(
private readonly MailMessageRepository $messageRepository,
private readonly MailProviderInterface $mailProvider,
private readonly EntityManagerInterface $em,
private readonly MailAccessChecker $accessChecker,
) {}
public function __invoke(Request $request, int $id): JsonResponse
{
$this->accessChecker->ensureCanAccessMail($this->getUser());
$message = $this->messageRepository->find($id);
if (null === $message) {
throw new NotFoundHttpException('Message not found');
}
$body = json_decode($request->getContent(), true);
$read = (bool) ($body['read'] ?? true);
try {
$this->mailProvider->markRead($message->getFolder()->getPath(), $message->getUid(), $read);
} catch (MailProviderException) {
// Non bloquant : on met quand meme a jour la BDD (sync IMAP au prochain cycle)
}
$message->setIsRead($read);
$this->em->flush();
return $this->json(['id' => $message->getId(), 'isRead' => $message->isRead()]);
}
}