Skip to content
Snippets Groups Projects
Commit aebfa25d authored by Jean-Philippe Metivier's avatar Jean-Philippe Metivier
Browse files

Merge branch 'release_7.0.0'

parents d2fb5e1a 8c8c74f6
No related branches found
No related tags found
No related merge requests found
Pipeline #33552 passed
...@@ -8,7 +8,8 @@ ...@@ -8,7 +8,8 @@
} }
], ],
"require": { "require": {
"unicaen/privilege": "^6" "unicaen/privilege": "^6",
"symfony/mailer": "^7"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
......
...@@ -3,17 +3,18 @@ ...@@ -3,17 +3,18 @@
namespace UnicaenMail\Controller; namespace UnicaenMail\Controller;
use Laminas\Http\Response; use Laminas\Http\Response;
use UnicaenMail\Service\Mail\MailServiceAwareTrait;
use Laminas\Mvc\Controller\AbstractActionController; use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\View\Model\ViewModel; use Laminas\View\Model\ViewModel;
use UnicaenMail\Service\Mail\MailServiceAwareTrait;
class MailController extends AbstractActionController { class MailController extends AbstractActionController
{
use MailServiceAwareTrait; use MailServiceAwareTrait;
public function indexAction(): ViewModel public function indexAction(): ViewModel
{ {
$filtre = $this->params()->fromQuery(); $filtre = $this->params()->fromQuery();
if (!isset($filtre['date']) OR $filtre['date'] === '') $filtre['date'] = '1W'; if (!isset($filtre['date']) or $filtre['date'] === '') $filtre['date'] = '1W';
$mails = $this->getMailService()->getMailsWithFiltre($filtre); $mails = $this->getMailService()->getMailsWithFiltre($filtre);
...@@ -43,13 +44,19 @@ class MailController extends AbstractActionController { ...@@ -43,13 +44,19 @@ class MailController extends AbstractActionController {
if (!isset($data['mail-to']) || !filter_var($data['mail-to'], FILTER_VALIDATE_EMAIL)) { if (!isset($data['mail-to']) || !filter_var($data['mail-to'], FILTER_VALIDATE_EMAIL)) {
return ['title' => "Envoyer un mail de test", 'error' => "L'adresse mail saisie n'est pas valide."]; return ['title' => "Envoyer un mail de test", 'error' => "L'adresse mail saisie n'est pas valide."];
} }
$mail = $this->getMailService()->sendMail($data['mail-to'], 'Mail de test', 'Ceci est un mail de test. <br/> <hr/>Merci de ne pas en tenir compte.');
if ($mail){
$mail = $this->getMailService()->sendMail(
to: $data['mail-to'],
subject: "Courrier électronique de test",
texte: "Ceci est un mail de test. <br/> <hr/>Merci de ne pas en tenir compte.",
);
$mail->setMotsClefs(['TEST']); $mail->setMotsClefs(['TEST']);
$this->getMailService()->update($mail); $this->getMailService()->update($mail);
} }
}
return ['title' => "Envoyer un mail de test"]; return ['title' => "Envoyer un mail de test"];
} }
public function reenvoiAction(): Response public function reenvoiAction(): Response
......
...@@ -16,6 +16,7 @@ class Mail { ...@@ -16,6 +16,7 @@ class Mail {
private ?string $destinataires = null; private ?string $destinataires = null;
private ?string $destinatairesInitials = null; private ?string $destinatairesInitials = null;
private ?string $copies = null; private ?string $copies = null;
private ?string $attachmentPaths = null;
/** Contenu *******************************************************************************************************/ /** Contenu *******************************************************************************************************/
...@@ -131,4 +132,14 @@ class Mail { ...@@ -131,4 +132,14 @@ class Mail {
$this->log = $log; $this->log = $log;
} }
public function getAttachmentPaths(): ?string
{
return $this->attachmentPaths;
}
public function setAttachmentPaths(?string $attachmentPaths): void
{
$this->attachmentPaths = $attachmentPaths;
}
} }
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="UnicaenMail\Entity\Db\Mail" table="unicaen_mail_mail"> <entity name="UnicaenMail\Entity\Db\Mail" table="unicaen_mail_mail">
<id name="id" type="integer" column="id"> <id name="id" type="integer" column="id">
<generator strategy="AUTO"/> <generator strategy="AUTO"/>
</id> </id>
<field name="dateEnvoi" type="datetime" column="date_envoi" nullable="false"/> <field name="dateEnvoi" type="datetime" column="date_envoi"/>
<field name="statusEnvoi" type="string" length="256" column="status_envoi" nullable="false" /> <field name="statusEnvoi" length="256" column="status_envoi"/>
<field name="destinataires" type="string" length="256" column="destinataires" nullable="false" /> <field name="destinataires" length="256" column="destinataires"/>
<field name="destinatairesInitials" type="string" length="256" column="destinataires_initials" nullable="true" /> <field name="destinatairesInitials" length="256" column="destinataires_initials" nullable="true"/>
<field name="copies" type="text" column="copies" nullable="true"/> <field name="copies" type="text" column="copies" nullable="true"/>
<field name="sujet" type="string" length="9999" column="sujet" nullable="true" /> <field name="sujet" length="9999" column="sujet" nullable="true"/>
<field name="corps" type="string" length="9999" column="corps" nullable="true" /> <field name="corps" length="9999" column="corps" nullable="true"/>
<field name="motsClefs" type="string" length="9999" column="mots_clefs" nullable="true" /> <field name="motsClefs" length="9999" column="mots_clefs" nullable="true"/>
<field name="attachmentPaths" type="text" column="attachment_paths" nullable="true"/>
<field name="log" type="string" length="9999" column="log" nullable="true" /> <field name="log" length="9999" column="log" nullable="true"/>
</entity> </entity>
</doctrine-mapping> </doctrine-mapping>
...@@ -4,28 +4,38 @@ namespace UnicaenMail\Service\Mail; ...@@ -4,28 +4,38 @@ namespace UnicaenMail\Service\Mail;
use DateInterval; use DateInterval;
use DateTime; use DateTime;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\NonUniqueResultException; use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\Exception\ORMException;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use DoctrineModule\Persistence\ProvidesObjectManager; use DoctrineModule\Persistence\ProvidesObjectManager;
use Exception; use Exception;
use RuntimeException; use RuntimeException;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mime\Email;
use UnicaenMail\Entity\Db\Mail; use UnicaenMail\Entity\Db\Mail;
use Laminas\Mail\Message; use Laminas\Mail\Message;
use Laminas\Mail\Transport\TransportInterface;
use Laminas\Mime\Message as MimeMessage; use Laminas\Mime\Message as MimeMessage;
use Laminas\Mime\Mime; use Laminas\Mime\Mime;
use Laminas\Mime\Part; use Laminas\Mime\Part;
use Laminas\Mvc\Controller\AbstractActionController; use Laminas\Mvc\Controller\AbstractActionController;
use UnicaenMail\Exception\NotFoundConfigException; use UnicaenMail\Exception\NotFoundConfigException;
/**
* @property EntityManager $objectManager
*/
class MailService { class MailService {
use ProvidesObjectManager; use ProvidesObjectManager;
private ?Mailer $mailer;
public function getMailer(): ?Mailer
{
return $this->mailer;
}
public function setMailer(?Mailer $mailer): void
{
$this->mailer = $mailer;
}
private ?string $entityClass = null; private ?string $entityClass = null;
private array $config = []; private array $config = [];
...@@ -50,44 +60,25 @@ class MailService { ...@@ -50,44 +60,25 @@ class MailService {
return $entity; return $entity;
} }
private ?TransportInterface $transport;
public function __construct(TransportInterface $transport)
{
$this->transport = $transport;
}
/** GESTION DES ENTITES *******************************************************************************************/ /** GESTION DES ENTITES *******************************************************************************************/
public function create(Mail $mail) : Mail public function create(Mail $mail) : Mail
{ {
try {
$this->objectManager->persist($mail); $this->objectManager->persist($mail);
$this->objectManager->flush($mail); $this->objectManager->flush($mail);
} catch (ORMException $e) {
throw new RuntimeException("Un problème est survenue lors de l'enregistrement en BD du Mail.", 0, $e);
}
return $mail; return $mail;
} }
public function update(Mail $mail) : Mail public function update(Mail $mail) : Mail
{ {
try {
$this->objectManager->flush($mail); $this->objectManager->flush($mail);
} catch (ORMException $e) {
throw new RuntimeException("Un problème est survenue lors de l'enregistrement en BD du Mail.", 0, $e);
}
return $mail; return $mail;
} }
public function delete(Mail $mail) : Mail public function delete(Mail $mail) : Mail
{ {
try {
$this->objectManager->remove($mail); $this->objectManager->remove($mail);
$this->objectManager->flush($mail); $this->objectManager->flush($mail);
} catch (ORMException $e) {
throw new RuntimeException("Un problème est survenue lors de l'enregistrement en BD du Mail.", 0, $e);
}
return $mail; return $mail;
} }
...@@ -163,28 +154,80 @@ class MailService { ...@@ -163,28 +154,80 @@ class MailService {
return $value; return $value;
} }
public function sendMail($to, $subject, $texte, ?string $module = null, $attachement_path = null, $copie = null, ?string $complement = null) : ?Mail public function transform(Mail $mail, ?string $module = null) : Email
{ {
try { try {
$fromEmail = $this->fetchValueFromConfig('from_email', $module); $fromEmail = $this->fetchValueFromConfig('from_email', $module);
$fromName = $this->fetchValueFromConfig('from_name', $module); $fromName = $this->fetchValueFromConfig('from_name', $module);
$doNotSend = $this->fetchValueFromConfig('do_not_send', $module); $subjectPrefix = $this->fetchValueFromConfig('subject_prefix', $module);
$redirect = $this->fetchValueFromConfig('redirect', $module); $redirect = $this->fetchValueFromConfig('redirect', $module);
$redirectTo = $this->fetchValueFromConfig('redirect_to', $module); $redirectTo = $this->fetchValueFromConfig('redirect_to', $module);
$subjectPrefix = $this->fetchValueFromConfig('subject_prefix', $module);
} catch (NotFoundConfigException $e) { } catch (NotFoundConfigException $e) {
throw new RuntimeException("Un problème est survenu lors de la récupération de valeurs de config",0,$e); throw new RuntimeException("Un problème est survenu lors de la récupération de valeurs de config",0,$e);
} }
$to = (is_string($mail->getDestinataires()))?[$mail->getDestinataires()]:$mail->getDestinataires();
$co = (is_string($mail->getCopies()))?[$mail->getCopies()]:$mail->getCopies();
$sujet = "[".$subjectPrefix. "] ".$mail->getSujet();
$corps = "<p><i>Ce courrier électronique vous a été adressé <strong>automatiquement</strong> par l'application ".$subjectPrefix.". </i></p>" . $mail->getCorps();
if ($redirect) {
$to = $redirectTo;
$sujet .= " {REDIR}";
$corps .= "<br/><br/><hr/><br/>";
$corps .= "Initialement envoyé à :";
$corps .= "<ul>";
foreach (explode(",",$mail->getDestinatairesInitials()) as $t) $corps .= "<li>" . $t . "</li>";
$corps .= "</ul>";
if ($mail->getCopies() !== null && !empty($co)) {
$corps .= "Copie à :";
$corps .= "<ul>";
foreach ($co as $e) $corps .= "<li>".$e."</li>";
$corps .= "</ul>";
}
}
$message = (new Email())
->from("'\"".$fromName."\" <".$fromEmail.">'")
->subject($sujet)
->text(strip_tags($corps))
->html($corps);
foreach ($to as $t) $message->to($t);
$attachments = ($mail->getAttachmentPaths())?explode("#<>#",$mail->getAttachmentPaths()):[];
foreach ($attachments as $path) {
$basename = basename($path);
$extension = (explode('.', $basename)[1])??'bin';
$message->attachFromPath($path, $basename, 'application/' . $extension);
}
if (!$redirect) {
foreach ($co as $c) $message->cc($c);
}
if ($mail->getCopies()) $message = $message->bcc($mail->getCopies());
return $message;
}
public function sendMail($to, $subject, $texte, ?string $module = null, $attachement_path = null, $copie = null) : ?Mail
{
try {
$doNotSend = $this->fetchValueFromConfig('do_not_send', $module);
$redirect = $this->fetchValueFromConfig('redirect', $module);
$redirectTo = $this->fetchValueFromConfig('redirect_to', $module);
} catch (NotFoundConfigException $e) {
throw new RuntimeException("Un problème est survenu lors de la récupération de valeurs de config",0,$e);
}
if ($to === "" OR $to === []) { if ($to=== null OR $to === "" OR $to === []) {
return null; return null;
} }
if (is_string($to)) $to=explode(',', $to); if (is_string($to)) $to=explode(',', $to);
if (!is_array($to)) $to = [$to]; if (!is_array($to)) $to = [$to];
if (is_string($copie)) $copie=explode(',', $copie); if (is_string($copie)) $copie=explode(',', $copie);
if (!is_array($copie)) $copie = [$copie]; if (!is_array($copie)) $copie = [$copie];
...@@ -201,81 +244,21 @@ class MailService { ...@@ -201,81 +244,21 @@ class MailService {
} }
if ($copie !== null and !empty($copie)) $mail->setCopies(implode(",", $copie)); if ($copie !== null and !empty($copie)) $mail->setCopies(implode(",", $copie));
$mail->setSujet($subject); $mail->setSujet($subject);
$sujet = '['.$subjectPrefix.'] ' . $subject;
if ($redirect) {
$sujet .= ' {REDIR}';
}
$message = (new Message())->setEncoding('UTF-8');
$message->setFrom($fromEmail, $fromName);
if ($redirect) {
foreach ($redirectTo as $e) $message->addTo($e);
} else {
foreach ($to as $e) $message->addTo($e);
if ($copie !== null and !empty($copie)) {
foreach ($copie as $e) {
if ($e !== null) $message->addCc($e);
}
}
}
$message->setSubject($sujet);
$mail->setCorps($texte); $mail->setCorps($texte);
$this->create($mail); if ($attachement_path !== null) {
$attachement_path = (is_string($attachement_path))?$attachement_path:implode("#<>#",$attachement_path);
$texte = "<p><i>Ce courrier électronique vous a été adressé <strong>automatiquement</strong> par l'application ".$subjectPrefix.". </i></p>" . $texte; $mail->setAttachmentPaths($attachement_path);
if ($complement) $texte = $complement.$texte;
if ($redirect) {
$texte .= "<br/><br/><hr/><br/>";
$texte .= "Initialement envoyé à :";
$texte .= "<ul>";
foreach (explode(",",$mail->getDestinatairesInitials()) as $t) $texte .= "<li>" . $t . "</li>";
$texte .= "</ul>";
if ($copie !== null && !empty($copie)) {
$texte .= "Copie à :";
$texte .= "<ul>";
foreach ($copie as $e) $texte .= "<li>".$e."</li>";
$texte .= "</ul>";
}
}
$parts = [];
$part = new Part($texte);
$part->type = Mime::TYPE_HTML;
$part->charset = 'UTF-8';
$parts[] = $part;
if ($attachement_path) {
if (!is_array($attachement_path)) $attachement_path = [$attachement_path];
foreach ($attachement_path as $attachement_pat) {
$attachement = new Part();
$attachement->setType("application/pdf");
$attachement->setContent(file_get_contents($attachement_pat));
$filename = explode('/', $attachement_pat);
$attachement->setFileName($filename[2]);
$attachement->setEncoding(Mime::ENCODING_BASE64);
$attachement->setDisposition(Mime::DISPOSITION_ATTACHMENT);
$parts[] = $attachement;
}
} }
$this->create($mail);
if ($doNotSend !== true) if ($doNotSend !== true)
{ {
$body = new MimeMessage(); try {
$body->setParts($parts); $email = $this->transform($mail, $module);
$message->setBody($body); $this->getMailer()->send($email);
} catch (TransportExceptionInterface $e) {
// var_dump($fromEmail); throw new RuntimeException("Échec de l'envoi du message", 0, $e);
// var_dump($fromName); }
// var_dump($doNotSend);
// var_dump($redirectTo);
// var_dump($subjectPrefix);
// die();
$this->transport->send($message);
$mail->setStatusEnvoi(Mail::SUCCESS); $mail->setStatusEnvoi(Mail::SUCCESS);
} else { } else {
$mail->setStatusEnvoi(Mail::NOTSENT); $mail->setStatusEnvoi(Mail::NOTSENT);
......
...@@ -4,10 +4,10 @@ namespace UnicaenMail\Service\Mail; ...@@ -4,10 +4,10 @@ namespace UnicaenMail\Service\Mail;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Interop\Container\ContainerInterface; use Interop\Container\ContainerInterface;
use Laminas\Mail\Transport\Smtp;
use Laminas\Mail\Transport\SmtpOptions;
use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface; use Psr\Container\NotFoundExceptionInterface;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
class MailServiceFactory { class MailServiceFactory {
...@@ -20,14 +20,16 @@ class MailServiceFactory { ...@@ -20,14 +20,16 @@ class MailServiceFactory {
public function __invoke(ContainerInterface $container) : MailService public function __invoke(ContainerInterface $container) : MailService
{ {
$config = $container->get('Configuration')['unicaen-mail']; $config = $container->get('Configuration')['unicaen-mail'];
$transport = new Smtp(new SmtpOptions($config['transport_options'])); $transport = new EsmtpTransport(host: $config['transport_options']['host'], port: $config['transport_options']['port']);
$mailer = new Mailer($transport);
/** /**
* @var EntityManager $entityManager * @var EntityManager $entityManager
*/ */
$entityManager = $container->get('doctrine.entitymanager.orm_default'); $entityManager = $container->get('doctrine.entitymanager.orm_default');
$service = new MailService($transport); $service = new MailService();
$service->setMailer($mailer);
$service->setConfig($config); $service->setConfig($config);
$service->setEntityClass($config['mail_entity_class']); $service->setEntityClass($config['mail_entity_class']);
$service->setObjectManager($entityManager); $service->setObjectManager($entityManager);
......
...@@ -34,8 +34,8 @@ if (!isset($options['droits']) OR !isset($options['droits']['supprimer'])) { ...@@ -34,8 +34,8 @@ if (!isset($options['droits']) OR !isset($options['droits']['supprimer'])) {
<table id="mails-liste" class="table table-condensed table-hover"> <table id="mails-liste" class="table table-condensed table-hover">
<thead> <thead>
<tr> <tr>
<th> Destinataires </th>
<th data-type="num"> Date d'envoi </th> <th data-type="num"> Date d'envoi </th>
<th> Destinataires </th>
<th> Statut </th> <th> Statut </th>
<th> Sujet </th> <th> Sujet </th>
<th> Infos </th> <th> Infos </th>
...@@ -45,6 +45,7 @@ if (!isset($options['droits']) OR !isset($options['droits']['supprimer'])) { ...@@ -45,6 +45,7 @@ if (!isset($options['droits']) OR !isset($options['droits']['supprimer'])) {
<tbody> <tbody>
<?php foreach ($mails as $mail) : ?> <?php foreach ($mails as $mail) : ?>
<tr> <tr>
<td data-order="<?php echo $mail->getDateEnvoi()->getTimestamp(); ?>"> <?php echo $mail->getDateEnvoi()->format('d/m/Y <br/> H:i'); ?> </td>
<td> <td>
<?php $destinataires = explode(",",$mail->getDestinataires()); ?> <?php $destinataires = explode(",",$mail->getDestinataires()); ?>
<ul> <ul>
...@@ -76,7 +77,6 @@ if (!isset($options['droits']) OR !isset($options['droits']['supprimer'])) { ...@@ -76,7 +77,6 @@ if (!isset($options['droits']) OR !isset($options['droits']['supprimer'])) {
<?php endif; ?> <?php endif; ?>
</td> </td>
<td data-order="<?php echo $mail->getDateEnvoi()->getTimestamp(); ?>"> <?php echo $mail->getDateEnvoi()->format('d/m/Y <br/> H:i'); ?> </td>
<td> <td>
<span class="badge <?php echo $mail->getStatusEnvoi(); ?>"> <span class="badge <?php echo $mail->getStatusEnvoi(); ?>">
<?php echo $mail->getStatusEnvoi(); ?> <?php echo $mail->getStatusEnvoi(); ?>
......
...@@ -48,6 +48,7 @@ $canTest = $this->isAllowed(MailPrivileges::getResourceId(MailPrivileges::MAIL_A ...@@ -48,6 +48,7 @@ $canTest = $this->isAllowed(MailPrivileges::getResourceId(MailPrivileges::MAIL_A
if (jQuery().dataTable) { if (jQuery().dataTable) {
$('#mails-liste').DataTable({ $('#mails-liste').DataTable({
"lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "Tous"]], "lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "Tous"]],
order: [[0, 'desc']],
"columnDefs": [ "columnDefs": [
{targets: 5, orderable: false, searchable: false}, {targets: 5, orderable: false, searchable: false},
], ],
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment