From f09db0ebdb4ec0b44f883fec91448011d105ceef Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Mon, 17 Oct 2022 16:07:05 +0300 Subject: [PATCH] ref --- application/Espo/Binding.php | 9 ++- application/Espo/Core/Mail/Sender.php | 24 +++---- application/Espo/Modules/Crm/Binding.php | 44 ++++++++++++ .../DefaultMessageHeadersPreparator.php | 69 +++++++++++++++++++ .../MassEmail/MessageHeadersPreparator.php | 41 +++++++++++ .../MassEmail/MessagePreparator/Data.php | 56 +++++++++++++++ .../Crm/Tools/MassEmail/SendingProcessor.php | 56 ++++++++------- 7 files changed, 252 insertions(+), 47 deletions(-) create mode 100644 application/Espo/Modules/Crm/Binding.php create mode 100644 application/Espo/Modules/Crm/Tools/MassEmail/DefaultMessageHeadersPreparator.php create mode 100644 application/Espo/Modules/Crm/Tools/MassEmail/MessageHeadersPreparator.php create mode 100644 application/Espo/Modules/Crm/Tools/MassEmail/MessagePreparator/Data.php diff --git a/application/Espo/Binding.php b/application/Espo/Binding.php index f88030c1e4..1941c7c6e7 100644 --- a/application/Espo/Binding.php +++ b/application/Espo/Binding.php @@ -229,11 +229,10 @@ class Binding implements BindingProcessor 'Espo\\Core\\Sms\\SenderFactory' ); - $binder - ->bindImplementation( - 'Espo\\Core\\Authentication\\Jwt\\KeyFactory', - 'Espo\\Core\\Authentication\\Jwt\\DefaultKeyFactory' - ); + $binder->bindImplementation( + 'Espo\\Core\\Authentication\\Jwt\\KeyFactory', + 'Espo\\Core\\Authentication\\Jwt\\DefaultKeyFactory' + ); $binder ->for('Espo\\Core\\Authentication\\Oidc\\TokenValidator') diff --git a/application/Espo/Core/Mail/Sender.php b/application/Espo/Core/Mail/Sender.php index e3630f2abb..96c5f0891e 100644 --- a/application/Espo/Core/Mail/Sender.php +++ b/application/Espo/Core/Mail/Sender.php @@ -44,19 +44,17 @@ use Espo\Entities\Attachment; use Espo\Entities\Email; use Espo\ORM\EntityManager; -use Laminas\{ - Mime\Message as MimeMessage, - Mime\Part as MimePart, - Mime\Mime as Mime, - Mail\Header\Sender as SenderHeader, - Mail\Header\MessageId as MessageIdHeader, - Mail\Header\ContentType as ContentTypeHeader, - Mail\Message, - Mail\Transport\SmtpOptions, - Mail\Transport\Envelope, - Mail\Transport\Smtp as SmtpTransport, - Mail\Protocol\Exception\RuntimeException as ProtocolRuntimeException, -}; +use Laminas\Mail\Header\ContentType as ContentTypeHeader; +use Laminas\Mail\Header\MessageId as MessageIdHeader; +use Laminas\Mail\Header\Sender as SenderHeader; +use Laminas\Mail\Message; +use Laminas\Mail\Protocol\Exception\RuntimeException as ProtocolRuntimeException; +use Laminas\Mail\Transport\Envelope; +use Laminas\Mail\Transport\Smtp as SmtpTransport; +use Laminas\Mail\Transport\SmtpOptions; +use Laminas\Mime\Message as MimeMessage; +use Laminas\Mime\Mime as Mime; +use Laminas\Mime\Part as MimePart; use Exception; use InvalidArgumentException; diff --git a/application/Espo/Modules/Crm/Binding.php b/application/Espo/Modules/Crm/Binding.php new file mode 100644 index 0000000000..54e9be58a3 --- /dev/null +++ b/application/Espo/Modules/Crm/Binding.php @@ -0,0 +1,44 @@ +bindImplementation( + 'Espo\\Modules\\Crm\\Tools\\MassEmail\\MessageHeadersPreparator', + 'Espo\\Modules\\Crm\\Tools\\MassEmail\\DefaultMessageHeadersPreparator' + ); + } +} diff --git a/application/Espo/Modules/Crm/Tools/MassEmail/DefaultMessageHeadersPreparator.php b/application/Espo/Modules/Crm/Tools/MassEmail/DefaultMessageHeadersPreparator.php new file mode 100644 index 0000000000..ab6617545a --- /dev/null +++ b/application/Espo/Modules/Crm/Tools/MassEmail/DefaultMessageHeadersPreparator.php @@ -0,0 +1,69 @@ +config = $config; + } + + public function prepare(Headers $headers, Data $data): void + { + $id = $data->getId(); + + $header = new XQueueItemId(); + $header->setId($id); + + $headers->addHeader($header); + $headers->addHeaderLine('Precedence', 'bulk'); + + if (!$this->config->get('massEmailDisableMandatoryOptOutLink')) { + $optOutUrl = $this->getSiteUrl() . '?entryPoint=unsubscribe&id=' . $id; + + $headers->addHeaderLine('List-Unsubscribe', '<' . $optOutUrl . '>'); + } + } + + private function getSiteUrl(): string + { + return + $this->config->get('massEmailSiteUrl') ?? + $this->config->get('siteUrl'); + } +} diff --git a/application/Espo/Modules/Crm/Tools/MassEmail/MessageHeadersPreparator.php b/application/Espo/Modules/Crm/Tools/MassEmail/MessageHeadersPreparator.php new file mode 100644 index 0000000000..264411ed3d --- /dev/null +++ b/application/Espo/Modules/Crm/Tools/MassEmail/MessageHeadersPreparator.php @@ -0,0 +1,41 @@ +id = $id; + $this->senderParams = $senderParams; + } + + public function getId(): string + { + return $this->id; + } + + public function getSenderParams(): SenderParams + { + return $this->senderParams; + } +} diff --git a/application/Espo/Modules/Crm/Tools/MassEmail/SendingProcessor.php b/application/Espo/Modules/Crm/Tools/MassEmail/SendingProcessor.php index 880c6b7d81..47fe068138 100644 --- a/application/Espo/Modules/Crm/Tools/MassEmail/SendingProcessor.php +++ b/application/Espo/Modules/Crm/Tools/MassEmail/SendingProcessor.php @@ -34,6 +34,7 @@ use Espo\Core\Mail\Exceptions\NoSmtp; use Espo\Core\Mail\SenderParams; use Espo\Core\Mail\SmtpParams; use Espo\Entities\Attachment; +use Espo\Modules\Crm\Tools\MassEmail\MessagePreparator\Data; use Espo\ORM\Collection; use Laminas\Mail\Message; @@ -43,7 +44,6 @@ use Espo\Entities\EmailAddress; use Espo\Core\Exceptions\Error; use Espo\Core\Mail\EmailSender; -use Espo\Core\Mail\Mail\Header\XQueueItemId; use Espo\Core\Mail\Sender; use Espo\Core\ORM\EntityManager; use Espo\Core\Utils\Config; @@ -76,6 +76,7 @@ class SendingProcessor private AccountFactory $accountFactory; private CampaignService $campaignService; private EmailTemplateService $emailTemplateService; + private MessageHeadersPreparator $headersPreparator; public function __construct( Config $config, @@ -85,7 +86,8 @@ class SendingProcessor Log $log, AccountFactory $accountFactory, CampaignService $campaignService, - EmailTemplateService $emailTemplateService + EmailTemplateService $emailTemplateService, + MessageHeadersPreparator $headersPreparator ) { $this->config = $config; $this->entityManager = $entityManager; @@ -95,6 +97,7 @@ class SendingProcessor $this->accountFactory = $accountFactory; $this->campaignService = $campaignService; $this->emailTemplateService = $emailTemplateService; + $this->headersPreparator = $headersPreparator; } /** @@ -288,6 +291,7 @@ class SendingProcessor $emailData['body'] = $body; + /** @var Email $email */ $email = $this->entityManager ->getRDBRepositoryByClass(Email::class) ->getNew(); @@ -300,57 +304,44 @@ class SendingProcessor return null; } - $email->set('to', $emailAddress); + $email->addToAddress($emailAddress); if ($massEmail->getFromAddress()) { - $email->set('from', $massEmail->getFromAddress()); + $email->setFromAddress($massEmail->getFromAddress()); } - if ($massEmail->getReplyToAddress()) { - $email->set('replyTo', $massEmail->getReplyToAddress()); + $replyToAddress = $massEmail->getReplyToAddress(); + + if ($replyToAddress) { + $email->addReplyToAddress($replyToAddress); } return $email; } - /** - * @todo Refactor. Use composition with an interface. - */ - protected function prepareQueueItemMessage( + private function prepareQueueItemMessage( EmailQueueItem $queueItem, Sender $sender, Message $message, SenderParams $senderParams - ): SenderParams { + ): void { - $header = new XQueueItemId(); - $header->setId($queueItem->getId()); + $id = $queueItem->getId(); - $message->getHeaders()->addHeader($header); - $message->getHeaders()->addHeaderLine('Precedence', 'bulk'); + $this->headersPreparator->prepare($message->getHeaders(), new Data($id, $senderParams)); - if (!$this->config->get('massEmailDisableMandatoryOptOutLink')) { - $optOutUrl = $this->getSiteUrl() . '?entryPoint=unsubscribe&id=' . $queueItem->getId(); - - $message->getHeaders()->addHeaderLine('List-Unsubscribe', '<' . $optOutUrl . '>'); - } - - $fromAddress = - $senderParams->getFromAddress() ?? - $this->config->get('outboundEmailFromAddress'); + $fromAddress = $senderParams->getFromAddress(); if ( $this->config->get('massEmailVerp') && $fromAddress && strpos($fromAddress, '@') ) { - $bounceAddress = explode('@', $fromAddress)[0] . '+bounce-qid-' . $queueItem->getId() . + $bounceAddress = explode('@', $fromAddress)[0] . '+bounce-qid-' . $id . '@' . explode('@', $fromAddress)[1]; $sender->withEnvelopeOptions(['from' => $bounceAddress]); } - - return $senderParams; } private function setFailed(MassEmail $massEmail): void @@ -464,6 +455,11 @@ class SendingProcessor ); } + $senderParams = $senderParams->withFromAddress( + $massEmail->getFromAddress() ?? + $this->config->get('outboundEmailFromAddress') + ); + if ($massEmail->getFromName()) { $senderParams = $senderParams->withFromName($massEmail->getFromName()); } @@ -486,7 +482,7 @@ class SendingProcessor $message = new Message(); - $senderParams = $this->prepareQueueItemMessage($queueItem, $sender, $message, $senderParams); + $this->prepareQueueItemMessage($queueItem, $sender, $message, $senderParams); $sender ->withParams($senderParams) @@ -539,6 +535,8 @@ class SendingProcessor private function getSiteUrl(): string { - return $this->config->get('massEmailSiteUrl') ?? $this->config->get('siteUrl'); + return + $this->config->get('massEmailSiteUrl') ?? + $this->config->get('siteUrl'); } }