All checks were successful
Symfony CI - Install, Test, Build, Attest & Deploy / 🚀 Deploy to Production (push) Successful in 54s
- Templates : retire les blocs partenaire SITECONSEIL (home, prestation), le DPO SITECONSEIL (rgpd), la SECTION 1 Opérateur Technique (hosting), et les mentions DEV BY/Développé par dans les footers. - Traductions (fr/en/es/cn/ger) : supprime les clés siteconseil_partner, siteconseil_referral, hosting_tech_operator_*, et bascule hosting_signalement_email vers signalement@e-cosplay.fr. - AmazonSesClient : passe l'expéditeur à no-reply@e-cosplay.fr. - SitemapSubscriber : retire l'image siteconseil.png et supprime l'asset associé. - Keycloak : URL auth.e-cosplay.fr, realm ecosplay, client ecosplay_web (env + nelmio_security CSP). - Notifuse : NOTIFUSE_CLIENT_EMAIL=contact@e-cosplay.fr. - CONTRIBUTING.md : remplace l'entité par l'association E-Cosplay. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
94 lines
2.9 KiB
PHP
94 lines
2.9 KiB
PHP
<?php
|
||
|
||
namespace App\Service\Mailer;
|
||
|
||
use App\Entity\Mail;
|
||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||
use Symfony\Component\Mailer\Mailer;
|
||
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
|
||
use Symfony\Component\Mime\Email;
|
||
use Symfony\Component\Mime\Header\IdentificationHeader;
|
||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||
|
||
class AmazonSesClient
|
||
{
|
||
private Mailer $mailer;
|
||
|
||
public function __construct(
|
||
private UrlGeneratorInterface $urlGenerator,
|
||
EventDispatcherInterface $eventDispatcher
|
||
) {
|
||
$transport = new EsmtpTransport(
|
||
'email-smtp.eu-west-3.amazonaws.com',
|
||
587,
|
||
false,
|
||
$eventDispatcher
|
||
);
|
||
$transport->setUsername($_ENV['AMAZON_SES_PUBLIC'] ?? '');
|
||
$transport->setPassword($_ENV['AMAZON_SES_SECRET'] ?? '');
|
||
|
||
$this->mailer = new Mailer($transport);
|
||
}
|
||
|
||
/**
|
||
* Envoie un email HTML avec tracking invisible.
|
||
*/
|
||
public function send(string $html, string $address, string $subject): void
|
||
{
|
||
$email = (new Email())
|
||
->from('no-reply@e-cosplay.fr')
|
||
->to($address)
|
||
->subject($subject);
|
||
|
||
// Génération et ajout de l'en-tête Message-Id
|
||
$messageId = $email->generateMessageId();
|
||
$email->getHeaders()->add(new IdentificationHeader('Message-Id', $messageId));
|
||
|
||
$tracking = $this->generateTracking($email);
|
||
|
||
$dom = new \DOMDocument();
|
||
libxml_use_internal_errors(true);
|
||
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
|
||
libxml_clear_errors();
|
||
|
||
$img = $dom->createElement('img');
|
||
$img->setAttribute('src', $tracking['url']);
|
||
$img->setAttribute('width', '0');
|
||
$img->setAttribute('height', '0');
|
||
|
||
$body = $dom->getElementsByTagName('body')->item(0);
|
||
if ($body) {
|
||
$body->appendChild($img);
|
||
}
|
||
$newHtml = $dom->saveHTML();
|
||
|
||
$email->html($newHtml);
|
||
|
||
$this->mailer->send($email);
|
||
}
|
||
|
||
/**
|
||
* Génère les données de tracking et l’URL associée.
|
||
*
|
||
* @param Email $email
|
||
* @return array{object: Mail, url: string}
|
||
*/
|
||
private function generateTracking(Email $email): array
|
||
{
|
||
$messageIdHeader = $email->getHeaders()->get('message-id');
|
||
$messageFormat = $messageIdHeader ? $messageIdHeader->getBody()[0] : '';
|
||
$messageFormat = str_replace('@e-cosplay.fr', '', $messageFormat);
|
||
|
||
$mailData = new Mail();
|
||
$mailData->setDest($email->getTo()[0]->getAddress());
|
||
$mailData->setSubject($email->getSubject());
|
||
$mailData->setMessageId($messageFormat);
|
||
$mailData->setStatus('draft');
|
||
|
||
return [
|
||
'object' => $mailData,
|
||
'url' => 'https://mainframe.esy-web.dev' . $this->urlGenerator->generate('app_tracking', ['slug' => $messageFormat]),
|
||
];
|
||
}
|
||
}
|