Merge pull request #5462 from AngelFQC/BT21613

Internal: Restoring mail conf variables
pull/5539/head
Nicolas Ducoulombier 1 year ago committed by GitHub
commit 119efed26f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      composer.json
  2. 163
      composer.lock
  3. 3
      config/packages/dev/mailer.yaml
  4. 10
      config/packages/mailer.yaml
  5. 17
      config/packages/messenger.yaml
  6. 3
      config/packages/test/mailer.yaml
  7. 4
      config/packages/test/messenger.yaml
  8. 5
      config/services.yaml
  9. 8
      public/main/admin/email_tester.php
  10. 145
      public/main/inc/lib/api.lib.php
  11. 19
      public/main/inc/lib/notification.lib.php
  12. 9
      public/main/inc/lib/usermanager.lib.php
  13. 38
      src/CoreBundle/Entity/Listener/MessageListener.php
  14. 6
      src/CoreBundle/Entity/Message.php
  15. 62
      src/CoreBundle/MessageHandler/MessageHandler.php
  16. 39
      src/CoreBundle/Migrations/AbstractMigrationChamilo.php
  17. 31
      src/CoreBundle/Migrations/Schema/V200/Version20240506164100.php
  18. 4
      src/CoreBundle/Resources/config/listeners.yml
  19. 3
      src/CoreBundle/Resources/views/Mailer/Default/default.text.twig
  20. 122
      src/CoreBundle/ServiceHelper/MailHelper.php
  21. 7
      src/CoreBundle/Settings/MailSettingsSchema.php
  22. 63
      src/CoreBundle/State/MessageProcessor.php

@ -95,6 +95,7 @@
"laminas/laminas-permissions-acl": "~2.8",
"league/csv": "^9.7",
"league/glide-symfony": "^2.0",
"league/html-to-markdown": "^5.1",
"league/mime-type-detection": "^1.7",
"lexik/jwt-authentication-bundle": "^2.20",
"maennchen/zipstream-php": "^2.1",
@ -120,6 +121,7 @@
"symfony/apache-pack": "^1.0",
"symfony/asset": "6.4.*",
"symfony/cache": "6.4.*",
"symfony/doctrine-messenger": "6.4.*",
"symfony/dotenv": "6.4.*",
"symfony/expression-language": "6.4.*",
"symfony/flex": "^2.4",

163
composer.lock generated

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "eb1defbff521d77a305a9e6dc17a60fb",
"content-hash": "de805232bd8fece99b4564930dedb852",
"packages": [
{
"name": "a2lix/auto-form-bundle",
@ -5467,6 +5467,95 @@
},
"time": "2023-12-14T15:52:00+00:00"
},
{
"name": "league/html-to-markdown",
"version": "5.1.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/html-to-markdown.git",
"reference": "0b4066eede55c48f38bcee4fb8f0aa85654390fd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/0b4066eede55c48f38bcee4fb8f0aa85654390fd",
"reference": "0b4066eede55c48f38bcee4fb8f0aa85654390fd",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-xml": "*",
"php": "^7.2.5 || ^8.0"
},
"require-dev": {
"mikehaertl/php-shellcommand": "^1.1.0",
"phpstan/phpstan": "^1.8.8",
"phpunit/phpunit": "^8.5 || ^9.2",
"scrutinizer/ocular": "^1.6",
"unleashedtech/php-coding-standard": "^2.7 || ^3.0",
"vimeo/psalm": "^4.22 || ^5.0"
},
"bin": [
"bin/html-to-markdown"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.2-dev"
}
},
"autoload": {
"psr-4": {
"League\\HTMLToMarkdown\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Colin O'Dell",
"email": "colinodell@gmail.com",
"homepage": "https://www.colinodell.com",
"role": "Lead Developer"
},
{
"name": "Nick Cernis",
"email": "nick@cern.is",
"homepage": "http://modernnerd.net",
"role": "Original Author"
}
],
"description": "An HTML-to-markdown conversion helper for PHP",
"homepage": "https://github.com/thephpleague/html-to-markdown",
"keywords": [
"html",
"markdown"
],
"support": {
"issues": "https://github.com/thephpleague/html-to-markdown/issues",
"source": "https://github.com/thephpleague/html-to-markdown/tree/5.1.1"
},
"funding": [
{
"url": "https://www.colinodell.com/sponsor",
"type": "custom"
},
{
"url": "https://www.paypal.me/colinpodell/10.00",
"type": "custom"
},
{
"url": "https://github.com/colinodell",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/league/html-to-markdown",
"type": "tidelift"
}
],
"time": "2023-07-12T21:21:09+00:00"
},
{
"name": "league/mime-type-detection",
"version": "1.15.0",
@ -10003,6 +10092,78 @@
],
"time": "2024-03-19T09:28:31+00:00"
},
{
"name": "symfony/doctrine-messenger",
"version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/doctrine-messenger.git",
"reference": "f850f471765aac77b89b6f9a2a09712a5faed1bd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/f850f471765aac77b89b6f9a2a09712a5faed1bd",
"reference": "f850f471765aac77b89b6f9a2a09712a5faed1bd",
"shasum": ""
},
"require": {
"doctrine/dbal": "^2.13|^3|^4",
"php": ">=8.1",
"symfony/messenger": "^5.4|^6.0|^7.0",
"symfony/service-contracts": "^2.5|^3"
},
"conflict": {
"doctrine/persistence": "<1.3"
},
"require-dev": {
"doctrine/persistence": "^1.3|^2|^3",
"symfony/property-access": "^5.4|^6.0|^7.0",
"symfony/serializer": "^5.4|^6.0|^7.0"
},
"type": "symfony-messenger-bridge",
"autoload": {
"psr-4": {
"Symfony\\Component\\Messenger\\Bridge\\Doctrine\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Doctrine Messenger Bridge",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/doctrine-messenger/tree/v6.4.7"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-04-18T09:22:46+00:00"
},
{
"name": "symfony/dotenv",
"version": "v6.4.4",

@ -1,3 +0,0 @@
framework:
mailer:
dsn: 'null://null'

@ -1,3 +1,13 @@
framework:
mailer:
dsn: '%env(MAILER_DSN)%'
when@dev:
framework:
mailer:
dsn: 'null://null'
when@test:
framework:
mailer:
dsn: 'null://null'

@ -10,14 +10,17 @@ framework:
# failed: 'doctrine://default?queue_name=failed'
# sync: 'sync://'
routing:
# Route your messages to the transports
'Chamilo\CoreBundle\Entity\Message': sync_priority_high
when@test:
framework:
messenger:
transports:
sync_priority_high: 'in-memory://'
# when@test:
#when@prod:
# framework:
# messenger:
# transports:
# # replace with your transport name here (e.g., my_transport: 'in-memory://')
# # For more Messenger testing tools, see https://github.com/zenstruck/messenger-test
# async: 'in-memory://'
# mail_async: "%env(MESSENGER_TRANSPORT_DSN)%"
#
# routing:
# 'Symfony\Component\Mailer\Messenger\SendEmailMessage': mail_async

@ -1,3 +0,0 @@
framework:
mailer:
dsn: 'null://null'

@ -1,4 +0,0 @@
framework:
messenger:
transports:
sync_priority_high: 'in-memory://'

@ -91,6 +91,11 @@ services:
$persistProcessor: '@api_platform.doctrine.orm.state.persist_processor'
$removeProcessor: '@api_platform.doctrine.orm.state.remove_processor'
Chamilo\CoreBundle\State\MessageProcessor:
bind:
$persistProcessor: '@api_platform.doctrine.orm.state.persist_processor'
$removeProcessor: '@api_platform.doctrine.orm.state.remove_processor'
Chamilo\CoreBundle\EventSubscriber\AnonymousUserSubscriber:
tags:
- name: kernel.event_subscriber

@ -4,6 +4,8 @@
* Index page of the admin tools.
*/
// Resetting the course id.
use Chamilo\CoreBundle\Framework\Container;
$cidReset = true;
// Including some necessary chamilo files.
@ -11,6 +13,8 @@ require_once __DIR__.'/../inc/global.inc.php';
api_protect_admin_script();
$settingsManager = Container::getSettingsManager();
// Setting the section (for the tabs).
$this_section = SECTION_PLATFORM_ADMIN;
$toolName = get_lang('E-mail tester');
@ -42,7 +46,9 @@ if ($form->validate()) {
$values['subject'],
$values['content'],
UserManager::formatUserFullName($user),
$user->getEmail()
'true' === $settingsManager->getSetting('mail.smtp_unique_sender')
? $settingsManager->getSetting('mail.smtp_from_email')
: $user->getEmail()
);
Display::addFlash(

@ -11,6 +11,7 @@ use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Entity\UserCourseCategory;
use Chamilo\CoreBundle\Exception\NotAllowedException;
use Chamilo\CoreBundle\Framework\Container;
use Chamilo\CoreBundle\ServiceHelper\MailHelper;
use Chamilo\CourseBundle\Entity\CGroup;
use Chamilo\CourseBundle\Entity\CLp;
use ChamiloSession as Session;
@ -7106,6 +7107,49 @@ function api_format_time($time, $originFormat = 'php')
return $formattedTime;
}
function api_set_noreply_and_from_address_to_mailer(
TemplatedEmail $email,
array $sender,
array $replyToAddress = []
): void {
$noReplyAddress = api_get_setting('noreply_email_address');
$avoidReplyToAddress = false;
if (!empty($noReplyAddress)) {
// $avoidReplyToAddress = api_get_configuration_value('mail_no_reply_avoid_reply_to');
}
// Default values
$notification = new Notification();
$defaultSenderName = $notification->getDefaultPlatformSenderName();
$defaultSenderEmail = $notification->getDefaultPlatformSenderEmail();
// If the parameter is set don't use the admin.
$senderName = !empty($sender['name']) ? $sender['name'] : $defaultSenderName;
$senderEmail = !empty($sender['email']) ? $sender['email'] : $defaultSenderEmail;
// Send errors to the platform admin
$email
->getHeaders()
->addIdHeader('Errors-To', api_get_setting('admin.administrator_email'))
;
if (!$avoidReplyToAddress && !empty($replyToAddress)) {
$email->addReplyTo(new Address($replyToAddress['mail'], $replyToAddress['name']));
}
if ('true' === api_get_setting('mail.smtp_unique_sender')) {
$senderName = $defaultSenderName;
$senderEmail = $defaultSenderEmail;
$email->sender(new Address($senderEmail, $senderName));
}
if ($senderEmail) {
$email->from(new Address($senderEmail, $senderName));
}
}
/**
* Sends an email
* Sender name and email can be specified, if not specified
@ -7134,93 +7178,24 @@ function api_mail_html(
$extra_headers = [],
$data_file = [],
$embeddedImage = false,
$additionalParameters = []
$additionalParameters = [],
string $sendErrorTo = null
) {
if (!api_valid_email($recipientEmail)) {
return false;
}
// Default values
$notification = new Notification();
$defaultEmail = $notification->getDefaultPlatformSenderEmail();
$defaultName = $notification->getDefaultPlatformSenderName();
// If the parameter is set don't use the admin.
$senderName = !empty($senderName) ? $senderName : $defaultName;
$senderEmail = !empty($senderEmail) ? $senderEmail : $defaultEmail;
// Reply to first
$replyToName = '';
$replyToEmail = '';
if (isset($extra_headers['reply_to'])) {
$replyToEmail = $extra_headers['reply_to']['mail'];
$replyToName = $extra_headers['reply_to']['name'];
}
try {
$bus = Container::getMessengerBus();
//$sendMessage = new \Chamilo\CoreBundle\Message\SendMessage();
//$bus->dispatch($sendMessage);
$message = new TemplatedEmail();
$message->subject($subject);
$mailHelper = Container::$container->get(MailHelper::class);
$list = api_get_setting('announcement.send_all_emails_to', true);
if (!empty($list) && isset($list['emails'])) {
foreach ($list['emails'] as $email) {
$message->cc($email);
}
}
// Attachment
if (!empty($data_file)) {
foreach ($data_file as $file_attach) {
if (!empty($file_attach['path']) && !empty($file_attach['filename'])) {
$message->attachFromPath($file_attach['path'], $file_attach['filename']);
}
}
}
$noReply = api_get_setting('noreply_email_address');
$automaticEmailText = '';
if (!empty($noReply)) {
$automaticEmailText = '<br />'.get_lang('This is an automatic email message. Please do not reply to it.');
}
$params = [
'mail_header_style' => api_get_setting('mail.mail_header_style'),
'mail_content_style' => api_get_setting('mail.mail_content_style'),
'link' => $additionalParameters['link'] ?? '',
'automatic_email_text' => $automaticEmailText,
'content' => $body,
'theme' => api_get_visual_theme(),
];
if (!empty($senderEmail)) {
$message->from(new Address($senderEmail, $senderName));
}
if (!empty($recipientEmail)) {
$message->to(new Address($recipientEmail, $recipientName));
}
if (!empty($replyToEmail)) {
$message->replyTo(new Address($replyToEmail, $replyToName));
}
$message
->htmlTemplate('@ChamiloCore/Mailer/Default/default.html.twig')
->textTemplate('@ChamiloCore/Mailer/Default/default.text.twig')
;
$message->context($params);
Container::getMailer()->send($message);
return true;
} catch (Exception $e) {
error_log($e->getMessage());
}
return 1;
return $mailHelper->send(
$recipientName,
$recipientEmail,
$subject,
$body,
$senderName,
$senderEmail,
$extra_headers,
$data_file,
$embeddedImage,
$additionalParameters,
$sendErrorTo
);
}
/**

@ -1,6 +1,8 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Framework\Container;
/**
* Notification class
* This class provides methods for the Notification management.
@ -58,13 +60,21 @@ class Notification extends Model
public function __construct()
{
$this->table = Database::get_main_table(TABLE_NOTIFICATION);
if ($smtpFromEmail = api_get_setting('mail.smtp_from_email')) {
$this->adminEmail = $smtpFromEmail;
if ($smtpFromName = api_get_setting('mail.smtp_from_name')) {
$this->adminName = $smtpFromName;
}
} else {
// Default no-reply email
$this->adminEmail = api_get_setting('noreply_email_address');
$this->adminName = api_get_setting('siteName');
$this->titlePrefix = '['.api_get_setting('siteName').'] ';
// If no-reply email doesn't exist or is something '@example.com', use the admin name/email
if (empty($this->adminEmail) || substr($this->adminEmail, -12) === '@example.com') {
// If no-reply email doesn't exist use the admin name/email
if (empty($this->adminEmail)) {
$this->adminEmail = api_get_setting('emailAdministrator');
$this->adminName = api_get_person_name(
api_get_setting('administratorName'),
@ -74,6 +84,7 @@ class Notification extends Model
);
}
}
}
/**
* @return string
@ -307,8 +318,8 @@ class Notification extends Model
$userInfo['mail'],
Security::filter_terms($titleToNotification),
Security::filter_terms($content),
$this->adminName,
$this->adminEmail,
!empty($senderInfo['complete_name']) ? $senderInfo['complete_name'] : $this->adminName,
!empty($senderInfo['email']) ? $senderInfo['email'] : $this->adminEmail,
$extraHeaders,
$attachments,
false

@ -457,7 +457,12 @@ class UserManager
$emailSubject,
$emailBody,
$sender_name,
$email_admin
$email_admin,
[],
[],
false,
[],
$creatorEmail
);
$emailBody = $tpl->render('@ChamiloCore/Mailer/Legacy/new_user_second_email_confirmation.html.twig');
@ -482,6 +487,7 @@ class UserManager
null,
null,
null,
[],
$creatorEmail
);
} else {
@ -514,6 +520,7 @@ class UserManager
null,
null,
null,
[],
$creatorEmail
);
}

@ -1,38 +0,0 @@
<?php
declare(strict_types=1);
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\Entity\Listener;
use Chamilo\CoreBundle\Entity\Message;
use Doctrine\ORM\Event\PostPersistEventArgs;
use Symfony\Component\Messenger\MessageBusInterface;
class MessageListener
{
public function __construct(
private MessageBusInterface $bus
) {}
public function postPersist(Message $message, PostPersistEventArgs $args): void
{
if ($message) {
// Creates an outbox version, if message is sent in the inbox.
if (Message::MESSAGE_TYPE_INBOX === $message->getMsgType()) {
/*$messageSent = clone $message;
$messageSent
->setMsgType(Message::MESSAGE_TYPE_OUTBOX)
->setRead(true)
->setReceivers(null)
;
$args->getEntityManager()->persist($messageSent);
$args->getEntityManager()->flush();*/
// Dispatch to the Messenger bus. Function MessageHandler.php will send the message.
$this->bus->dispatch($message);
}
}
}
}

@ -16,9 +16,9 @@ use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use Chamilo\CoreBundle\Entity\Listener\MessageListener;
use Chamilo\CoreBundle\Repository\MessageRepository;
use Chamilo\CoreBundle\State\MessageByGroupStateProvider;
use Chamilo\CoreBundle\State\MessageProcessor;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
@ -33,7 +33,6 @@ use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Index(columns: ['group_id'], name: 'idx_message_group')]
#[ORM\Index(columns: ['msg_type'], name: 'idx_message_type')]
#[ORM\Entity(repositoryClass: MessageRepository::class)]
#[ORM\EntityListeners([MessageListener::class])]
#[ApiResource(
operations: [
new Get(security: "is_granted('VIEW', object)"),
@ -58,7 +57,8 @@ use Symfony\Component\Validator\Constraints as Assert;
denormalizationContext: [
'groups' => ['message:write'],
],
security: "is_granted('ROLE_USER')"
security: "is_granted('ROLE_USER')",
processor: MessageProcessor::class,
)]
#[ApiFilter(filterClass: OrderFilter::class, properties: ['title', 'sendDate'])]
#[ApiFilter(

@ -1,62 +0,0 @@
<?php
declare(strict_types=1);
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\MessageHandler;
use Chamilo\CoreBundle\Entity\Message;
use Chamilo\CoreBundle\Entity\MessageRelUser;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Mime\Address;
#[AsMessageHandler]
class MessageHandler
{
public function __construct(
private readonly Mailer $mailer
) {}
public function __invoke(Message $message): void
{
if (Message::MESSAGE_TYPE_INBOX !== $message->getMsgType()) {
// Only send messages to the inbox.
return;
}
$email = (new TemplatedEmail())
->subject($message->getTitle())
->from(new Address($message->getSender()->getEmail(), $message->getSender()->getFirstname()))
->htmlTemplate('@ChamiloCore/Mailer/Default/default.html.twig')
->textTemplate('@ChamiloCore/Mailer/Default/default.text.twig')
;
foreach ($message->getReceivers() as $messageRelUser) {
$receiver = $messageRelUser->getReceiver();
$address = new Address($receiver->getEmail(), $receiver->getFirstname());
if (MessageRelUser::TYPE_TO === $messageRelUser->getReceiverType()) {
$email->addTo($address);
} elseif (MessageRelUser::TYPE_CC === $messageRelUser->getReceiverType()) {
$email->addBcc($address);
}
}
$params = [
'content' => $message->getContent(),
'automatic_email_text' => '',
'mail_header_style' => '',
'mail_content_style' => '',
'theme' => '',
];
$email->context($params);
try {
$this->mailer->send($email);
} catch (TransportExceptionInterface $e) {
error_log('MessageHandler exception: '.$e->getMessage());
}
}
}

@ -163,6 +163,21 @@ abstract class AbstractMigrationChamilo extends AbstractMigration
return false;
}
public function getMailConfigurationValue(string $variable, array $configuration = []): mixed
{
global $platform_email;
if ($configuration) {
$platform_email = $configuration;
}
if (isset($platform_email[$variable])) {
return $platform_email[$variable];
}
return false;
}
/**
* Remove a setting completely.
*
@ -332,4 +347,28 @@ abstract class AbstractMigrationChamilo extends AbstractMigration
return $this->entityManager->find(Session::class, $id);
}
public function getMailConfigurationValueFromFile(string $variable): ?string
{
global $platform_email;
$rootPath = $this->container->get('kernel')->getProjectDir();
$oldConfigPath = $rootPath.'/app/config/mail.conf.php';
$configFileLoaded = \in_array($oldConfigPath, get_included_files(), true);
if (!$configFileLoaded) {
include_once $oldConfigPath;
}
$settingValue = $this->getConfigurationValue($variable, $platform_email);
if (\is_bool($settingValue)) {
$selectedValue = var_export($settingValue, true);
} else {
$selectedValue = (string) $settingValue;
}
return $selectedValue;
}
}

@ -0,0 +1,31 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\Migrations\Schema\V200;
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo;
use Doctrine\DBAL\Schema\Schema;
class Version20240506164100 extends AbstractMigrationChamilo
{
/**
* @inheritDoc
*/
public function up(Schema $schema): void
{
$selectedMailValue = $this->getMailConfigurationValueFromFile('SMTP_UNIQUE_SENDER') ? 'true' : 'false';
$this->addSql("INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url, access_url_changeable, access_url_locked) VALUES ('smtp_unique_sender', null, null, 'mail', '$selectedMailValue', 'smtp_unique_sender', null, '', null, 1, 1, 1)");
$selectedMailValue = $this->getMailConfigurationValueFromFile('SMTP_FROM_EMAIL');
$this->addSql("INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url, access_url_changeable, access_url_locked) VALUES ('smtp_from_email', null, null, 'mail', '$selectedMailValue', 'smtp_from_email', null, '', null, 1, 1, 1)");
$selectedMailValue = $this->getMailConfigurationValueFromFile('SMTP_FROM_NAME');
$this->addSql("INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url, access_url_changeable, access_url_locked) VALUES ('smtp_from_name', null, null, 'mail', '$selectedMailValue', 'smtp_from_name', null, '', null, 1, 1, 1)");
}
}

@ -94,10 +94,6 @@ services:
tags:
- {name: doctrine.orm.entity_listener, entity_manager: default, lazy: true}
Chamilo\CoreBundle\Entity\Listener\MessageListener:
tags:
- {name: doctrine.orm.entity_listener, entity_manager: default, lazy: true}
Chamilo\CoreBundle\Entity\Listener\SkillRelUserListener:
arguments:
- '@Chamilo\CoreBundle\Settings\SettingsManager'

@ -1,3 +0,0 @@
{{ automatic_email_text }}
{{ content }}

@ -0,0 +1,122 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\ServiceHelper;
use Exception;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\BodyRendererInterface;
final class MailHelper
{
public function __construct(
private readonly MailerInterface $mailer,
private readonly BodyRendererInterface $bodyRenderer,
) {}
public function send(
string $recipientName,
string $recipientEmail,
string $subject,
string $body,
?string $senderName = null,
?string $senderEmail = null,
array $extra_headers = [],
array $data_file = [],
bool $embeddedImage = false,
array $additionalParameters = [],
?string $sendErrorTo = null,
): bool {
if (!api_valid_email($recipientEmail)) {
return false;
}
$templatedEmail = new TemplatedEmail();
api_set_noreply_and_from_address_to_mailer(
$templatedEmail,
['name' => $senderName, 'email' => $senderEmail],
!empty($extra_headers['reply_to']) ? $extra_headers['reply_to'] : []
);
if ($sendErrorTo) {
$templatedEmail
->getHeaders()
->addIdHeader('Errors-To', $sendErrorTo)
;
}
// Reply to first
$replyToName = '';
$replyToEmail = '';
if (isset($extra_headers['reply_to'])) {
$replyToEmail = $extra_headers['reply_to']['mail'];
$replyToName = $extra_headers['reply_to']['name'];
}
try {
$templatedEmail->subject($subject);
$list = api_get_setting('announcement.send_all_emails_to', true);
if (!empty($list) && isset($list['emails'])) {
foreach ($list['emails'] as $email) {
$templatedEmail->cc($email);
}
}
// Attachment
if (!empty($data_file)) {
foreach ($data_file as $file_attach) {
if (!empty($file_attach['path']) && !empty($file_attach['filename'])) {
$templatedEmail->attachFromPath($file_attach['path'], $file_attach['filename']);
}
}
}
$noReply = api_get_setting('noreply_email_address');
$automaticEmailText = '';
if (!empty($noReply)) {
$automaticEmailText = '<br />'.get_lang('This is an automatic email message. Please do not reply to it.');
}
$params = [
'mail_header_style' => api_get_setting('mail.mail_header_style'),
'mail_content_style' => api_get_setting('mail.mail_content_style'),
'link' => $additionalParameters['link'] ?? '',
'automatic_email_text' => $automaticEmailText,
'content' => $body,
'theme' => api_get_visual_theme(),
];
if (!empty($recipientEmail)) {
$templatedEmail->to(new Address($recipientEmail, $recipientName));
}
if (!empty($replyToEmail)) {
$templatedEmail->replyTo(new Address($replyToEmail, $replyToName));
}
$templatedEmail
->htmlTemplate('@ChamiloCore/Mailer/Default/default.html.twig')
->context($params)
;
$this->bodyRenderer->render($templatedEmail);
$this->mailer->send($templatedEmail);
return true;
} catch (Exception|TransportExceptionInterface $e) {
error_log($e->getMessage());
return false;
}
}
}

@ -31,6 +31,10 @@ class MailSettingsSchema extends AbstractSettingsSchema
'send_notification_score_in_percentage' => 'false',
'cron_notification_help_desk' => '',
'notifications_extended_footer_message' => '',
'smtp_unique_sender' => 'false',
'smtp_from_email' => '',
'smtp_from_name' => '',
]
)
;
@ -65,6 +69,9 @@ class MailSettingsSchema extends AbstractSettingsSchema
'help' => $this->settingArrayHelpValue('notifications_extended_footer_message'),
]
)
->add('smtp_unique_sender', YesNoType::class)
->add('smtp_from_email', EmailType::class)
->add('smtp_from_name', TextType::class)
;
$this->updateFormFieldsFromSettingsInfo($builder);

@ -0,0 +1,63 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\State;
use ApiPlatform\Metadata\DeleteOperationInterface;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Post;
use ApiPlatform\State\ProcessorInterface;
use Chamilo\CoreBundle\Entity\Message;
use Notification;
final class MessageProcessor implements ProcessorInterface
{
public function __construct(
private readonly ProcessorInterface $persistProcessor,
private readonly ProcessorInterface $removeProcessor,
) {}
public function process($data, Operation $operation, array $uriVariables = [], array $context = [])
{
if ($operation instanceof DeleteOperationInterface) {
return $this->removeProcessor->process($data, $operation, $uriVariables, $context);
}
$message = $this->persistProcessor->process($data, $operation, $uriVariables, $context);
assert($message instanceof Message);
if ($operation instanceof Post) {
if (Message::MESSAGE_TYPE_INBOX === $message->getMsgType()) {
$this->saveNotificationForInboxMessage($message);
}
}
return $message;
}
private function saveNotificationForInboxMessage(Message $message): void
{
$sender_info = api_get_user_info(
$message->getSender()->getId()
);
foreach ($message->getReceivers() as $receiver) {
$user = $receiver->getReceiver();
(new Notification())
->saveNotification(
$message->getId(),
Notification::NOTIFICATION_TYPE_MESSAGE,
[$user->getId()],
$message->getTitle(),
$message->getContent(),
$sender_info,
)
;
}
}
}
Loading…
Cancel
Save