This commit is contained in:
Yuri Kuznetsov
2025-06-25 10:42:31 +03:00
parent bedf805456
commit 09b94de327
12 changed files with 84 additions and 35 deletions
@@ -30,6 +30,7 @@
namespace Espo\Classes\FieldProcessing\Email;
use Espo\Core\Name\Field;
use Espo\Core\Name\Link;
use Espo\ORM\Entity;
use Espo\ORM\Name\Attribute;
use Espo\Repositories\EmailAddress as EmailAddressRepository;
@@ -44,17 +45,15 @@ use Espo\Entities\User;
*/
class StringDataLoader implements Loader
{
private EntityManager $entityManager;
private User $user;
private const LINK_EMAIL_ADDRESSES = Link::EMAIL_ADDRESSES;
/** @var array<string, string> */
private $fromEmailAddressNameCache = [];
public function __construct(EntityManager $entityManager, User $user)
{
$this->entityManager = $entityManager;
$this->user = $user;
}
public function __construct(
private EntityManager $entityManager,
private User $user
) {}
public function process(Entity $entity, Params $params): void
{
@@ -63,8 +62,7 @@ class StringDataLoader implements Loader
$userEmailAddressIdList = [];
$emailAddressCollection = $this->entityManager
->getRDBRepository(User::ENTITY_TYPE)
->getRelation($this->user, 'emailAddresses')
->getRelation($this->user, self::LINK_EMAIL_ADDRESSES)
->select([Attribute::ID])
->find();
@@ -33,8 +33,8 @@ use Espo\Core\Acl;
use Espo\Core\Exceptions\BadRequest;
use Espo\Core\Exceptions\Forbidden;
use Espo\Core\Mail\Account\SendingAccountProvider;
use Espo\Core\Mail\ConfigDataProvider;
use Espo\Core\Record\Hook\SaveHook;
use Espo\Core\Utils\Config;
use Espo\Entities\Email;
use Espo\Entities\User;
use Espo\ORM\Entity;
@@ -47,8 +47,8 @@ class CheckFromAddress implements SaveHook
public function __construct(
private User $user,
private SendingAccountProvider $sendingAccountProvider,
private Config $config,
private Acl $acl,
private ConfigDataProvider $configDataProvider,
) {}
public function process(Entity $entity): void
@@ -88,12 +88,11 @@ class CheckFromAddress implements SaveHook
if (
$system &&
$this->config->get('outboundEmailIsShared') &&
$system->getEmailAddress()
$this->configDataProvider->isOutboundEmailShared() &&
$system->getEmailAddress() &&
$fromAddress === strtolower($system->getEmailAddress())
) {
if ($fromAddress === strtolower($system->getEmailAddress())) {
return;
}
return;
}
throw new Forbidden("Not allowed 'from' address.");
@@ -29,6 +29,7 @@
namespace Espo\Classes\Select\Email\Where\ItemConverters;
use Espo\Core\Name\Link;
use Espo\Core\Select\Where\ItemConverter;
use Espo\Core\Select\Where\Item;
@@ -237,8 +238,7 @@ class InFolder implements ItemConverter
protected function getEmailAddressIdList(): array
{
$emailAddressList = $this->entityManager
->getRDBRepository(User::ENTITY_TYPE)
->getRelation($this->user, 'emailAddresses')
->getRelation($this->user, Link::EMAIL_ADDRESSES)
->select([Attribute::ID])
->find();
@@ -35,6 +35,7 @@ use Espo\Core\Action\Params;
use Espo\Core\Exceptions\Forbidden;
use Espo\Core\Exceptions\NotFound;
use Espo\Core\Name\Field;
use Espo\Core\Name\Link;
use Espo\Core\ORM\EntityManager;
use Espo\Core\ORM\Type\FieldType;
use Espo\Core\Record\ActionHistory\Action;
@@ -218,7 +219,7 @@ class Merger
/** @var iterable<EmailAddress> $collection */
$collection = $this->entityManager
->getRelation($entity, 'emailAddresses')
->getRelation($entity, Link::EMAIL_ADDRESSES)
->find();
foreach ($collection as $entity) {
@@ -287,7 +288,7 @@ class Merger
$entityDefs = $this->entityManager->getDefs()->getEntity($entityType);
$ignoreList = [
'emailAddresses',
Link::EMAIL_ADDRESSES,
'phoneNumbers',
];
@@ -29,6 +29,7 @@
namespace Espo\Core\FieldProcessing\EmailAddress;
use Espo\Core\Name\Link;
use Espo\Core\ORM\Repository\Option\SaveOption;
use Espo\Core\ORM\Type\FieldType;
use Espo\Entities\EmailAddress;
@@ -50,6 +51,8 @@ class Saver implements SaverInterface
private const ATTR_EMAIL_ADDRESS_IS_OPTED_OUT = 'emailAddressIsOptedOut';
private const ATTR_EMAIL_ADDRESS_IS_INVALID = 'emailAddressIsInvalid';
private const LINK_EMAIL_ADDRESSES = Link::EMAIL_ADDRESSES;
public function __construct(
private EntityManager $entityManager,
private ApplicationState $applicationState,
@@ -421,7 +424,7 @@ class Saver implements SaverInterface
if ($emailAddressOld) {
$this->entityManager
->getRelation($entity, 'emailAddresses')
->getRelation($entity, self::LINK_EMAIL_ADDRESSES)
->unrelate($emailAddressOld, [SaveOption::SKIP_HOOKS => true]);
}
}
@@ -493,13 +496,13 @@ class Saver implements SaverInterface
if ($emailAddressOld) {
$entityRepository
->getRelation($entity, 'emailAddresses')
->getRelation($entity, self::LINK_EMAIL_ADDRESSES)
->unrelate($emailAddressOld, [SaveOption::SKIP_HOOKS => true]);
}
}
$entityRepository
->getRelation($entity, 'emailAddresses')
->getRelation($entity, self::LINK_EMAIL_ADDRESSES)
->relate($emailAddressNew, null, [SaveOption::SKIP_HOOKS => true]);
if ($entity->has(self::ATTR_EMAIL_ADDRESS_IS_OPTED_OUT)) {
@@ -30,6 +30,7 @@
namespace Espo\Core\Mail\Account\GroupAccount\Hooks;
use Espo\Core\Name\Field;
use Espo\Core\Name\Link;
use Laminas\Mail\Message;
use Espo\Core\Mail\Account\GroupAccount\AccountFactory as GroupAccountFactory;
@@ -543,7 +544,7 @@ class AfterFetch implements AfterFetchInterface
$contact = $this->entityManager
->getRDBRepository(Contact::ENTITY_TYPE)
->join('emailAddresses', 'emailAddressesMultiple')
->join(Link::EMAIL_ADDRESSES, 'emailAddressesMultiple')
->where([
'emailAddressesMultiple.id' => $email->get('fromEmailAddressId'),
])
@@ -555,7 +556,7 @@ class AfterFetch implements AfterFetchInterface
if (!$case->get('accountId')) {
$lead = $this->entityManager
->getRDBRepository(Lead::ENTITY_TYPE)
->join('emailAddresses', 'emailAddressesMultiple')
->join(Link::EMAIL_ADDRESSES, 'emailAddressesMultiple')
->where([
'emailAddressesMultiple.id' => $email->get('fromEmailAddressId')
])
@@ -41,4 +41,9 @@ class ConfigDataProvider
{
return $this->config->get('outboundEmailFromAddress');
}
public function isOutboundEmailShared(): bool
{
return (bool) $this->config->get('outboundEmailIsShared');
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2025 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://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 Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Name;
/**
* @since 9.2.0
*/
class Link
{
public const EMAIL_ADDRESSES = 'emailAddresses';
}
+4 -5
View File
@@ -32,6 +32,7 @@ namespace Espo\Tools\App;
use Espo\Core\Authentication\Util\MethodProvider as AuthenticationMethodProvider;
use Espo\Core\Mail\ConfigDataProvider as EmailConfigDataProvider;
use Espo\Core\Name\Field;
use Espo\Core\Name\Link;
use Espo\Core\Utils\SystemUser;
use Espo\Entities\DashboardTemplate;
use Espo\Entities\Email;
@@ -51,7 +52,6 @@ use Espo\Core\Utils\Log;
use Espo\Core\Utils\Metadata;
use Espo\Entities\User;
use Espo\Entities\Preferences;
use Espo\ORM\Collection;
use Espo\ORM\EntityManager;
use stdClass;
use Throwable;
@@ -281,16 +281,15 @@ class AppService
{
$user = $this->user;
$outboundEmailIsShared = $this->config->get('outboundEmailIsShared');
$outboundEmailIsShared = $this->emailConfigDataProvider->isOutboundEmailShared();
$outboundEmailFromAddress = $this->emailConfigDataProvider->getSystemOutboundAddress();
$emailAddressList = [];
$userEmailAddressList = [];
/** @var Collection<EmailAddress> $emailAddressCollection */
/** @var iterable<EmailAddress> $emailAddressCollection */
$emailAddressCollection = $this->entityManager
->getRDBRepositoryByClass(User::class)
->getRelation($user, 'emailAddresses')
->getRelation($user, Link::EMAIL_ADDRESSES)
->find();
foreach ($emailAddressCollection as $emailAddress) {
@@ -31,6 +31,7 @@ namespace Espo\Tools\App;
use Espo\Core\Mail\ConfigDataProvider as EmailConfigDataProvider;
use Espo\Core\Utils\ThemeManager;
use Espo\Entities\Email;
use Espo\Entities\Settings;
use Espo\ORM\Entity;
use Espo\ORM\EntityManager;
@@ -368,8 +369,8 @@ class SettingsService
}
if (
!$this->acl->checkScope('Email', 'create') ||
!$this->config->get('outboundEmailIsShared')
!$this->acl->checkScope(Email::ENTITY_TYPE, Acl\Table::ACTION_CREATE) ||
!$this->emailConfigDataProvider->isOutboundEmailShared()
) {
unset($data->outboundEmailFromAddress);
unset($data->outboundEmailFromName);
+5 -2
View File
@@ -52,6 +52,7 @@ use Espo\Core\Mail\Sender;
use Espo\Core\Mail\SenderParams;
use Espo\Core\Mail\Smtp\HandlerProcessor;
use Espo\Core\Mail\SmtpParams;
use Espo\Core\Name\Link;
use Espo\Core\ORM\Repository\Option\SaveOption;
use Espo\Core\Utils\Config;
use Espo\Core\Utils\Json;
@@ -77,6 +78,8 @@ use const FILTER_VALIDATE_EMAIL;
*/
class SendService
{
private const LINK_EMAIL_ADDRESSES = Link::EMAIL_ADDRESSES;
/** @var string[] */
private array $notAllowedStatusList = [
Email::STATUS_ARCHIVED,
@@ -127,7 +130,7 @@ class SendService
throw new BadRequest("Empty To address.");
}
$systemIsShared = $this->config->get('outboundEmailIsShared');
$systemIsShared = $this->configDataProvider->isOutboundEmailShared();
$systemFromName = $this->config->get('outboundEmailFromName');
$systemFromAddress = $this->configDataProvider->getSystemOutboundAddress();
@@ -139,7 +142,7 @@ class SendService
// @todo Use getEmailAddressGroup.
/** @var Collection<EmailAddress> $emailAddressCollection */
$emailAddressCollection = $this->entityManager
->getRelation($user, 'emailAddresses')
->getRelation($user, self::LINK_EMAIL_ADDRESSES)
->find();
foreach ($emailAddressCollection as $ea) {
@@ -31,6 +31,7 @@ namespace Espo\Tools\EmailNotification;
use Espo\Core\Field\LinkParent;
use Espo\Core\Name\Field;
use Espo\Core\Name\Link;
use Espo\Core\Notification\EmailNotificationHandler;
use Espo\Core\Mail\SenderParams;
use Espo\Core\Utils\Config\ApplicationConfig;
@@ -766,7 +767,7 @@ class Processor
}
$emailAddresses = $this->entityManager
->getRelation($user, 'emailAddresses')
->getRelation($user, Link::EMAIL_ADDRESSES)
->find();
foreach ($emailAddresses as $ea) {