Mailer.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Service\Mailer;
  4. use App\Entity\Message\ReportEmail;
  5. use App\Enum\Core\EmailSendingTypeEnum;
  6. use App\Enum\Message\MessageStatusEnum;
  7. use App\Service\Mailer\Model\MailerModelInterface;
  8. use App\Service\ServiceIterator\Mailer\BuilderIterator;
  9. use App\Service\Utils\StringsUtils;
  10. use App\Enum\Message\ReportMessageSatusEnum;
  11. use Doctrine\Common\Collections\ArrayCollection;
  12. use Doctrine\ORM\EntityManagerInterface;
  13. use Symfony\Bridge\Twig\Mime\TemplatedEmail;
  14. use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
  15. use Symfony\Component\Mailer\MailerInterface;
  16. use Symfony\Component\Mime\Address;
  17. use Symfony\Component\Mime\Email as SymfonyEmail;
  18. /**
  19. * Classe Mailer : Service assurant l'envoie d'un mail à un destinataire
  20. */
  21. class Mailer
  22. {
  23. public function __construct(
  24. private MailerInterface $symfonyMailer,
  25. private string $opentalentNoReplyEmailAddress,
  26. private BuilderIterator $builderIterator,
  27. private StringsUtils $stringsUtils,
  28. private EntityManagerInterface $entityManager
  29. )
  30. {
  31. }
  32. /**
  33. * Main fonction qui itère les différentes étapes nécessaires à l'envoie d'un email
  34. * - Le Build
  35. * - Le Send
  36. * - Le Reporting
  37. *
  38. * @param MailerModelInterface $mailerModel
  39. * @throws \Exception
  40. */
  41. public function main(MailerModelInterface $mailerModel): void{
  42. $builderService = $this->builderIterator->getBuilderFor($mailerModel);
  43. $emailsCollection = $builderService->build($mailerModel);
  44. // @todo
  45. //$emailsCollection = $this->reduceEmailsCollectionInPreproduction($emailsCollection);
  46. foreach ($emailsCollection as $email){
  47. $this->send($email);
  48. $this->persistEmailEntity($email);
  49. }
  50. $this->report($emailsCollection);
  51. $this->entityManager->flush();
  52. }
  53. /**
  54. * Fonction d'envoie
  55. * @param EmailInterface $email
  56. */
  57. public function send(EmailInterface $email): void{
  58. //On créer le mail
  59. $symfonyMail = $this->createSymfonyEmail($email);
  60. $this->addRecipients($symfonyMail, $email);
  61. $this->addHeaders($symfonyMail, $email);
  62. // @todo
  63. //$this->addAttachments();
  64. //On tente d'envoyer
  65. try {
  66. $this->symfonyMailer->send($symfonyMail);
  67. $email->getEmailEntity()->setStatus(MessageStatusEnum::SEND()->getValue());
  68. $email->getEmailEntity()->setDateSent(new \DateTime('now'));
  69. } catch (\Exception $e) {
  70. $email->getEmailEntity()->setStatus(MessageStatusEnum::FAILED()->getValue());
  71. }
  72. }
  73. /**
  74. * Fonction de rapport
  75. * @param ArrayCollection $emails
  76. */
  77. public function report(ArrayCollection $emails): void{
  78. $delivered = [];
  79. $unDelivered = [];
  80. foreach ($emails as $email){
  81. $emailRecipients = $email->getEmailRecipients();
  82. /** @var EmailRecipient $emailRecipient */
  83. foreach ($emailRecipients as $emailRecipient){
  84. if($emailRecipient->getSendStatus() === ReportMessageSatusEnum::MISSING()->getValue()){
  85. $unDelivered[] = $emailRecipient;
  86. }else if($emailRecipient->getSendStatus() === ReportMessageSatusEnum::DELIVERED()->getValue()){
  87. $delivered[] = $emailRecipient;
  88. }
  89. }
  90. }
  91. $templatedMail = (new TemplatedEmail())
  92. ->from($this->opentalentNoReplyEmailAddress)
  93. ->subject(sprintf('Rapport d\'envoie du message : %s', $emails->first()->getEmailEntity()->getAbout()))
  94. ->htmlTemplate('@templates/emails/report.html.twig')
  95. ->context(
  96. [
  97. 'email_example' => $emails->first()->getEmailEntity(),
  98. 'delivered' => $delivered,
  99. 'unDelivered' => $unDelivered
  100. ]
  101. )
  102. ->addTo(new Address($this->opentalentNoReplyEmailAddress))
  103. ;
  104. try {
  105. $this->symfonyMailer->send($templatedMail);
  106. } catch (TransportExceptionInterface $e) {
  107. }
  108. }
  109. /**
  110. * Persist l'Email et les ReportEmail
  111. * @param Email $email
  112. */
  113. public function persistEmailEntity(Email $email){
  114. $emailEntity = $email->getEmailEntity();
  115. /** @var EmailRecipient $emailRecipient */
  116. foreach ($email->getEmailRecipients() as $emailRecipient){
  117. $report = (new ReportEmail())
  118. ->setAddressEmail($emailRecipient->getEmailAddress())
  119. ->setAccess($emailRecipient->getAccess())
  120. ->setOrganization($emailRecipient->getOrganization())
  121. ->setDateSend(new \DateTime('now'))
  122. ->setStatus($emailRecipient->getSendStatus())
  123. ;
  124. $emailEntity->addReport($report);
  125. }
  126. $this->entityManager->persist($emailEntity);
  127. }
  128. /**
  129. * Reduit le nombre d'emails a envoyer si on ne se trouve pas en prod
  130. * @param ArrayCollection $emailsCollection
  131. */
  132. public function reduceEmailsCollectionInPreproduction(ArrayCollection $emailsCollection): ArrayCollection {
  133. if($_ENV['env'] === 'prod') return $emailsCollection;
  134. $startEmails = $emailsCollection->slice(0, 10);
  135. $endEmails = $emailsCollection->slice($emailsCollection->count() - 11, 10);
  136. return new ArrayCollection([...$startEmails, ...$endEmails]);
  137. }
  138. /**
  139. * @param SymfonyEmail $symfonyMail
  140. * @param Email $email
  141. */
  142. public function addHeaders(SymfonyEmail $symfonyMail, Email $email){
  143. // $symfonyMail->getHeaders()->addTextHeader('List-Unsubscribe','mailto:'.$email->getOriginator().'?subject=désabonnement');
  144. $symfonyMail->getHeaders()->addTextHeader('X-ID-OT', $email->getEmailEntity()->getUniqueSendId());
  145. }
  146. /**
  147. * Création du Mail qui sera envoyé via le Mailer de Symfony
  148. * @param Email $email
  149. * @return SymfonyEmail
  150. */
  151. public function createSymfonyEmail(Email $email): SymfonyEmail{
  152. return (new SymfonyEmail())
  153. ->from($email->getFrom())
  154. ->subject($email->getEmailEntity()->getAbout())
  155. ->html($email->getContent())
  156. ->text($this->stringsUtils->convertHtmlToText($email->getContent()))
  157. ;
  158. }
  159. /**
  160. * On ajoute les destinataires suivant le type d'envoie souhaité
  161. * @param SymfonyEmail $symfonyMail
  162. * @param Address $addressesMail
  163. */
  164. public function addRecipients(SymfonyEmail $symfonyMail, Email $email): void{
  165. foreach ($email->getEmailRecipients() as $emailRecipient){
  166. $addressMail = new Address($emailRecipient->getEmailAddress(), $emailRecipient->getName());
  167. switch($emailRecipient->getSendType()){
  168. case EmailSendingTypeEnum::TO()->getValue():
  169. $symfonyMail->addTo($addressMail);
  170. break;
  171. case EmailSendingTypeEnum::BBC()->getValue():
  172. $symfonyMail->addBcc($addressMail);
  173. break;
  174. case EmailSendingTypeEnum::CC()->getValue():
  175. $symfonyMail->addCc($addressMail);
  176. break;
  177. }
  178. }
  179. }
  180. }