mirror of
https://github.com/espocrm/espocrm.git
synced 2026-06-28 06:56:05 +00:00
ref
This commit is contained in:
@@ -31,17 +31,24 @@ namespace Espo\Controllers;
|
||||
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
use Espo\Services\EmailTemplate as Service;
|
||||
use Espo\Core\Exceptions\ForbiddenSilent;
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Tools\EmailTemplate\Data;
|
||||
use Espo\Tools\EmailTemplate\Service;
|
||||
|
||||
use Espo\Core\{
|
||||
Controllers\Record,
|
||||
Api\Request,
|
||||
};
|
||||
use Espo\Core\Api\Request;
|
||||
use Espo\Core\Controllers\Record;
|
||||
|
||||
use stdClass;
|
||||
|
||||
class EmailTemplate extends Record
|
||||
{
|
||||
|
||||
/**
|
||||
* @throws BadRequest
|
||||
* @throws NotFound
|
||||
* @throws ForbiddenSilent
|
||||
*/
|
||||
public function actionParse(Request $request): stdClass
|
||||
{
|
||||
$id = $request->getQueryParam('id');
|
||||
@@ -50,22 +57,21 @@ class EmailTemplate extends Record
|
||||
throw new BadRequest("No `id`.");
|
||||
}
|
||||
|
||||
return (object) $this->getEmailTempalteService()->parse(
|
||||
$id,
|
||||
[
|
||||
'emailAddress' => $request->getQueryParam('emailAddress'),
|
||||
'parentType' => $request->getQueryParam('parentType'),
|
||||
'parentId' => $request->getQueryParam('parentId'),
|
||||
'relatedType' => $request->getQueryParam('relatedType'),
|
||||
'relatedId' => $request->getQueryParam('relatedId'),
|
||||
],
|
||||
true
|
||||
);
|
||||
$data = Data::create()
|
||||
->withRelatedType($request->getQueryParam('relatedType'))
|
||||
->withRelatedId($request->getQueryParam('relatedId'))
|
||||
->withParentType($request->getQueryParam('parentType'))
|
||||
->withParentId($request->getQueryParam('parentId'))
|
||||
->withEmailAddress($request->getQueryParam('emailAddress'));
|
||||
|
||||
$result = $this->getEmailTemplateService()->process($id, $data);
|
||||
|
||||
return $result->getValueMap();
|
||||
|
||||
}
|
||||
|
||||
private function getEmailTempalteService(): Service
|
||||
private function getEmailTemplateService(): Service
|
||||
{
|
||||
/** @var Service */
|
||||
return $this->getRecordService();
|
||||
return $this->injectableFactory->create(Service::class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@ use Espo\Core\Templates\Entities\Person;
|
||||
use Espo\Modules\Crm\Entities\Contact;
|
||||
use Espo\Modules\Crm\Entities\Lead;
|
||||
use Espo\Tools\Email\Util;
|
||||
use Espo\Tools\EmailTemplate\Data as EmailTemplateData;
|
||||
use Espo\Tools\EmailTemplate\Params as EmailTemplateParams;
|
||||
use Espo\Tools\EmailTemplate\Service as EmailTemplateService;
|
||||
use Laminas\Mail\Message;
|
||||
|
||||
use Espo\Core\Mail\Account\Account;
|
||||
@@ -46,11 +49,9 @@ use Espo\Core\Mail\EmailSender;
|
||||
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\Core\Utils\DateTime as DateTimeUtil;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Utils\Log;
|
||||
|
||||
use Espo\Tools\Stream\Service as StreamService;
|
||||
use Espo\Services\EmailTemplate as EmailTemplateService;
|
||||
|
||||
use Espo\Entities\InboundEmail;
|
||||
use Espo\Entities\Email;
|
||||
@@ -77,7 +78,6 @@ class AfterFetch implements AfterFetchInterface
|
||||
private StreamService $streamService;
|
||||
private Config $config;
|
||||
private EmailSender $emailSender;
|
||||
private InjectableFactory $injectableFactory;
|
||||
private Log $log;
|
||||
private RoundRobin $roundRobin;
|
||||
private LeastBusy $leastBusy;
|
||||
@@ -85,27 +85,28 @@ class AfterFetch implements AfterFetchInterface
|
||||
private const DEFAULT_AUTOREPLY_LIMIT = 5;
|
||||
private const DEFAULT_AUTOREPLY_SUPPRESS_PERIOD = '2 hours';
|
||||
private GroupAccountFactory $groupAccountFactory;
|
||||
private EmailTemplateService $emailTemplateService;
|
||||
|
||||
public function __construct(
|
||||
EntityManager $entityManager,
|
||||
StreamService $streamService,
|
||||
Config $config,
|
||||
EmailSender $emailSender,
|
||||
InjectableFactory $injectableFactory,
|
||||
Log $log,
|
||||
RoundRobin $roundRobin,
|
||||
LeastBusy $leastBusy,
|
||||
GroupAccountFactory $groupAccountFactory
|
||||
GroupAccountFactory $groupAccountFactory,
|
||||
EmailTemplateService $emailTemplateService
|
||||
) {
|
||||
$this->entityManager = $entityManager;
|
||||
$this->streamService = $streamService;
|
||||
$this->config = $config;
|
||||
$this->emailSender = $emailSender;
|
||||
$this->injectableFactory = $injectableFactory;
|
||||
$this->log = $log;
|
||||
$this->roundRobin = $roundRobin;
|
||||
$this->leastBusy = $leastBusy;
|
||||
$this->groupAccountFactory = $groupAccountFactory;
|
||||
$this->emailTemplateService = $emailTemplateService;
|
||||
}
|
||||
|
||||
public function process(Account $account, Email $email, BeforeFetchResult $beforeFetchResult): void
|
||||
@@ -269,27 +270,29 @@ class AfterFetch implements AfterFetchInterface
|
||||
$entityHash[User::ENTITY_TYPE] = $user;
|
||||
}
|
||||
|
||||
$emailTemplateService = $this->getEmailTemplateService();
|
||||
|
||||
$replyData = $emailTemplateService->parse(
|
||||
$replyData = $this->emailTemplateService->process(
|
||||
$replyEmailTemplateId,
|
||||
['entityHash' => $entityHash],
|
||||
true
|
||||
EmailTemplateData::create()
|
||||
->withEntityHash($entityHash),
|
||||
EmailTemplateParams::create()
|
||||
->withApplyAcl(false)
|
||||
->withCopyAttachments(true)
|
||||
);
|
||||
|
||||
$subject = $replyData['subject'];
|
||||
$subject = $replyData->getSubject();
|
||||
|
||||
if ($case) {
|
||||
$subject = '[#' . $case->get('number'). '] ' . $subject;
|
||||
}
|
||||
|
||||
/** @var Email $reply */
|
||||
$reply = $this->entityManager->getRDBRepositoryByClass(Email::class)->getNew();
|
||||
|
||||
$reply->set('to', $fromAddress);
|
||||
$reply->set('subject', $subject);
|
||||
$reply->set('body', $replyData['body']);
|
||||
$reply->set('isHtml', $replyData['isHtml']);
|
||||
$reply->set('attachmentsIds', $replyData['attachmentsIds']);
|
||||
$reply
|
||||
->addToAddress($fromAddress)
|
||||
->setSubject($subject)
|
||||
->setBody($replyData->getBody())
|
||||
->setIsHtml($replyData->isHtml());
|
||||
|
||||
if ($email->has('teamsIds')) {
|
||||
$reply->set('teamsIds', $email->get('teamsIds'));
|
||||
@@ -335,6 +338,7 @@ class AfterFetch implements AfterFetchInterface
|
||||
$sender
|
||||
->withParams($senderParams)
|
||||
->withMessage($message)
|
||||
->withAttachments($replyData->getAttachmentList())
|
||||
->send($reply);
|
||||
|
||||
$this->entityManager->saveEntity($reply);
|
||||
@@ -344,12 +348,6 @@ class AfterFetch implements AfterFetchInterface
|
||||
}
|
||||
}
|
||||
|
||||
private function getEmailTemplateService(): EmailTemplateService
|
||||
{
|
||||
/** @var EmailTemplateService */
|
||||
return $this->injectableFactory->create(EmailTemplateService::class);
|
||||
}
|
||||
|
||||
private function createCase(GroupAccount $account, Email $email): void
|
||||
{
|
||||
$inboundEmail = $account->getEntity();
|
||||
|
||||
@@ -170,6 +170,9 @@ class Email extends Entity
|
||||
$this->get('createdById') !== ApplicationUser::SYSTEM_USER_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Revise.
|
||||
*/
|
||||
public function addAttachment(Attachment $attachment): void
|
||||
{
|
||||
if (!$this->id) {
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
namespace Espo\Services;
|
||||
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Repositories\EmailAddress as EmailAddressRepository;
|
||||
|
||||
use Espo\Tools\EmailTemplate\Processor;
|
||||
@@ -46,6 +47,8 @@ use Espo\Core\Di;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* @deprecated For bc. Use `Espo\Tools\EmailTemplate\Service`.
|
||||
*
|
||||
* @extends Record<\Espo\Entities\EmailTemplate>
|
||||
*/
|
||||
class EmailTemplate extends Record implements
|
||||
@@ -55,6 +58,8 @@ class EmailTemplate extends Record implements
|
||||
use Di\FieldUtilSetter;
|
||||
|
||||
/**
|
||||
* @deprecated For bc. Use `Espo\Tools\EmailTemplate\Processor`.
|
||||
*
|
||||
* @param array<string,mixed> $params
|
||||
* @return array{
|
||||
* subject: string,
|
||||
@@ -99,9 +104,11 @@ class EmailTemplate extends Record implements
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated For bc. Use `Espo\Tools\EmailTemplate\Service`.
|
||||
*
|
||||
* @param array<string,mixed> $params
|
||||
* @return array<string,mixed>
|
||||
* @throws \Espo\Core\Exceptions\ForbiddenSilent
|
||||
* @throws Forbidden
|
||||
* @throws NotFound
|
||||
*/
|
||||
public function parse(string $id, array $params = [], bool $copyAttachments = false): array
|
||||
|
||||
@@ -30,28 +30,18 @@
|
||||
namespace Espo\Tools\EmailTemplate;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
class Data
|
||||
{
|
||||
/**
|
||||
* @var array<string,Entity>
|
||||
*/
|
||||
/** @var array<string, Entity> */
|
||||
private $entityHash = [];
|
||||
|
||||
private ?string $emailAddress = null;
|
||||
|
||||
private ?Entity $parent = null;
|
||||
|
||||
private ?string $parentId = null;
|
||||
|
||||
private ?string $parentType = null;
|
||||
|
||||
private ?string $relatedId = null;
|
||||
|
||||
private ?string $relatedType = null;
|
||||
|
||||
private ?User $user = null;
|
||||
|
||||
/**
|
||||
|
||||
@@ -141,6 +141,13 @@ class Processor
|
||||
|
||||
$service->loadAdditionalFields($parent);
|
||||
|
||||
if (
|
||||
$params->applyAcl() &&
|
||||
!$this->aclManager->checkEntityRead($this->user, $parent)
|
||||
) {
|
||||
$parent = null;
|
||||
}
|
||||
|
||||
$data = $data->withParent($parent);
|
||||
}
|
||||
}
|
||||
@@ -159,6 +166,14 @@ class Processor
|
||||
if ($data->getRelatedId() && $data->getRelatedType()) {
|
||||
$related = $this->entityManager->getEntity($data->getRelatedType(), $data->getRelatedId());
|
||||
|
||||
if (
|
||||
$related &&
|
||||
$params->applyAcl() &&
|
||||
!$this->aclManager->checkEntityRead($this->user, $related)
|
||||
) {
|
||||
$related = null;
|
||||
}
|
||||
|
||||
if ($related) {
|
||||
$entityHash[$related->getEntityType()] = $related;
|
||||
}
|
||||
@@ -169,8 +184,6 @@ class Processor
|
||||
|
||||
$parent = $entityHash[self::KEY_PARENT] ?? null;
|
||||
|
||||
$htmlizer = null;
|
||||
|
||||
if ($parent && !$this->config->get('emailTemplateHtmlizerDisabled')) {
|
||||
$handlebarsInSubject = strpos($subject, '{{') !== false && strpos($subject, '}}') !== false;
|
||||
$handlebarsInBody = strpos($body, '{{') !== false && strpos($body, '}}') !== false;
|
||||
|
||||
91
application/Espo/Tools/EmailTemplate/Service.php
Normal file
91
application/Espo/Tools/EmailTemplate/Service.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2022 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Tools\EmailTemplate;
|
||||
|
||||
use Espo\Core\Acl;
|
||||
use Espo\Core\Exceptions\ForbiddenSilent;
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\Record\ServiceContainer;
|
||||
use Espo\Entities\EmailTemplate;
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
class Service
|
||||
{
|
||||
private Processor $processor;
|
||||
private User $user;
|
||||
private Acl $acl;
|
||||
private EntityManager $entityManager;
|
||||
|
||||
public function __construct(
|
||||
Processor $processor,
|
||||
User $user,
|
||||
Acl $acl,
|
||||
EntityManager $entityManager
|
||||
) {
|
||||
$this->processor = $processor;
|
||||
$this->user = $user;
|
||||
$this->acl = $acl;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an email data with an applied template.
|
||||
*
|
||||
* @throws NotFound
|
||||
* @throws ForbiddenSilent
|
||||
*/
|
||||
public function process(string $emailTemplateId, Data $data, ?Params $params = null): Result
|
||||
{
|
||||
/** @var ?EmailTemplate $emailTemplate */
|
||||
$emailTemplate = $this->entityManager->getEntityById(EmailTemplate::ENTITY_TYPE, $emailTemplateId);
|
||||
|
||||
if (!$emailTemplate) {
|
||||
throw new NotFound();
|
||||
}
|
||||
|
||||
$params ??= Params::create()
|
||||
->withApplyAcl(true)
|
||||
->withCopyAttachments(true);
|
||||
|
||||
if (
|
||||
$params->applyAcl() &&
|
||||
!$this->acl->checkEntityRead($emailTemplate)
|
||||
) {
|
||||
throw new ForbiddenSilent();
|
||||
}
|
||||
|
||||
if (!$data->getUser()) {
|
||||
$data = $data->withUser($this->user);
|
||||
}
|
||||
|
||||
return $this->processor->process($emailTemplate, $params, $data);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user