builderIterator->getBuilderFor($mailerModel); $emailsCollection = $builderService->build($mailerModel); $emailsCollection = $this->reduceEmailsCollectionInPreproduction($emailsCollection); /** @var Email $email */ foreach ($emailsCollection as $email) { // si l'email n'a pas de destinataire, on ne l'envoi pas... if ($email->getEmailRecipients()->isEmpty()) { $email->getEmailEntity()->setStatus(MessageStatusEnum::NO_RECIPIENT); continue; } // Envoi du mail $this->send($email); // Persistance de l'entité Email $this->persistEmailEntity($email); } // Envoi du rapport $this->sendReport($emailsCollection); $this->entityManager->flush(); return $emailsCollection; } /** * Fonction d'envoi. * * @throws TransportExceptionInterface * * @see MailerTest::testSend() */ public function send(Email $email): void { // On créé le mail $symfonyMail = $this->createSymfonyEmail($email); $this->addRecipients($symfonyMail, $email); $this->setAntiSpam($email, $symfonyMail->getTo()); $this->setSymfonyEmailContent($symfonyMail, $email); $this->addHeaders($symfonyMail, $email); // @todo // $this->addAttachments(); // On tente d'envoyer try { $this->symfonyMailer->send($symfonyMail); $email->getEmailEntity()->setStatus(MessageStatusEnum::SEND); $email->getEmailEntity()->setDateSent(new \DateTime('now')); } catch (\Exception $e) { $this->logger->error('Error while sending email'); $this->logger->error($e->getMessage()); $email->getEmailEntity()->setStatus(MessageStatusEnum::FAILED); } } /** * Envoi le rapport d'envoi. * * @param ArrayCollection $emails * * @see MailerTest::testSendReport() */ public function sendReport(ArrayCollection $emails): void { $reportEmail = $this->createReportEmail($emails); try { $this->symfonyMailer->send($reportEmail); } catch (TransportExceptionInterface $e) { $this->logger->error('Error while sending report'); $this->logger->error($e->getMessage()); } } /** * Création du Mail qui sera envoyé via le Mailer de Symfony. * * @see MailerTest::testCreateSymfonyEmail() */ public function createSymfonyEmail(Email $email, bool $isSystemEmail = false): SymfonyEmail { $addressMailFrom = $isSystemEmail ? new Address('ne-pas-repondre@opentalent.com', 'Opentalent') : new Address($email->getFrom(), $email->getFromName()); $symfonyEmail = (new SymfonyEmail()) ->from($addressMailFrom) ->subject($email->getEmailEntity()->getAbout()); if (!$isSystemEmail) { $symfonyEmail->replyTo($addressMailFrom) ->returnPath(Address::create('mail.report@opentalent.fr')); } return $symfonyEmail; } /** * @see MailerTest::testSetSymfonyEmailContent() */ public function setSymfonyEmailContent(SymfonyEmail $symfonyEmail, Email $email): void { $symfonyEmail ->html($email->getContent()) ->text($this->stringsUtils->convertHtmlToText($email->getContent())); } /** * Créé le Templated Email contenant le rapport d'envoi. * * @param ArrayCollection $emails * * @see MailerTest::testCreateReportEmail() */ public function createReportEmail(ArrayCollection $emails): TemplatedEmail { [$delivered, $unDelivered] = $this->getDeliveredAndUndelivered($emails); /** @var Email $email */ $email = $emails->first(); return (new TemplatedEmail()) ->from($this->opentalentNoReplyEmailAddress) ->subject(sprintf('Rapport d\'envoi du message : %s', $email->getEmailEntity()->getAbout())) ->htmlTemplate('@templates/emails/report.html.twig') ->context( [ 'email_example' => $email->getEmailEntity(), 'delivered' => $delivered, 'unDelivered' => $unDelivered, ] ) ->addTo(new Address($email->getFrom(), $email->getFromName())); } /** * Récupère les recipient delivered & undelivered de l'ensemble des emails. * * @param ArrayCollection $emails * * @return list * * @see MailerTest::testGetDeliveredAndUndelivered() */ public function getDeliveredAndUndelivered(ArrayCollection $emails): array { $delivered = []; $unDelivered = []; foreach ($emails as $email) { $emailRecipients = $email->getEmailRecipients(); /** @var EmailRecipient $emailRecipient */ foreach ($emailRecipients as $emailRecipient) { if (ReportMessageStatusEnum::MISSING === $emailRecipient->getSendStatus()) { $unDelivered[] = $emailRecipient; } elseif (ReportMessageStatusEnum::DELIVERED === $emailRecipient->getSendStatus()) { $delivered[] = $emailRecipient; } } } return [$delivered, $unDelivered]; } /** * Persist l'Email. * * @see MailerTest::testPersistEmailEntity() */ public function persistEmailEntity(Email $email): void { $emailEntity = $email->getEmailEntity(); /** @var EmailRecipient $emailRecipient */ foreach ($email->getEmailRecipients() as $emailRecipient) { $emailEntity->addReport($this->createReport($emailRecipient)); } $this->entityManager->persist($emailEntity); } /** * Création du rapport. * * @see MailerTest::testCreateReport() */ public function createReport(EmailRecipient $emailRecipient): ReportEmail { $reportEmail = new ReportEmail(); $reportEmail ->setAddressEmail($emailRecipient->getEmailAddress()) ->setAccess($emailRecipient->getAccess()) ->setOrganization($emailRecipient->getOrganization()) ->setDateSend(new \DateTime('now')) ->setStatus($emailRecipient->getSendStatus()); // Return en deux temps car setStatus renvoi un AbstractReport et non un ReportEmail return $reportEmail; } /** * Reduit le nombre d'emails a envoyer si on ne se trouve pas en prod. * * @param ArrayCollection $emailsCollection * * @return ArrayCollection * * @see MailerTest::testReduceEmailsCollectionInPreproduction() */ public function reduceEmailsCollectionInPreproduction(ArrayCollection $emailsCollection): ArrayCollection { if ('prod' !== $this->environnement->get(EnvironnementVarEnum::APP_ENV->value) && $emailsCollection->count() > 20) { $startEmails = $emailsCollection->slice(0, 10); $endEmails = $emailsCollection->slice($emailsCollection->count() - 11, 10); return new ArrayCollection([...$startEmails, ...$endEmails]); } return $emailsCollection; } /** * @see MailerTest::testAddHeaders() */ public function addHeaders(SymfonyEmail $symfonyMail, Email $email): void { $symfonyMail->getHeaders()->addTextHeader('List-Unsubscribe', 'mailto:' . $email->getFrom() . '?subject=désabonnement'); $symfonyMail->getHeaders()->addTextHeader('X-ID-OT', $email->getEmailEntity()->getUuid()->toString()); } /** * On change le #__#ANTISPAM_PERSON_EMAIL#__# par la liste des emails afin d'éviter le spamming sur l'envoi en masse. * * @param list
$addresses * * @see MailerTest::testSetAntiSpam() */ public function setAntiSpam(Email $email, array $addresses): void { // map des Address pour ne conserver qu'un tableau d'email $to = array_map(function (Address $address) { return $address->getAddress(); }, $addresses); $email->setContent(str_replace('#__#ANTISPAM_PERSON_EMAIL#__#', implode(',', $to), $email->getContent())); } /** * On ajoute les destinataires suivant le type d'envoi souhaité. * * @see MailerTest::testAddRecipients() */ public function addRecipients(SymfonyEmail $symfonyMail, Email $email): void { $allReadySend = []; foreach ($email->getEmailRecipients() as $emailRecipient) { $addressMail = new Address($emailRecipient->getEmailAddress(), $emailRecipient->getName()); // On envoi pas en double if (!in_array($addressMail, $allReadySend)) { $allReadySend[] = $addressMail; switch ($emailRecipient->getSendType()) { case EmailSendingTypeEnum::TO: $symfonyMail->addTo($addressMail); break; case EmailSendingTypeEnum::BBC: $symfonyMail->addBcc($addressMail); break; case EmailSendingTypeEnum::CC: $symfonyMail->addCc($addressMail); break; } } } } }