Spaces:
No application file
No application file
File size: 4,516 Bytes
d2897cd |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
<?php
namespace Mautic\EmailBundle\MonitoredEmail\Processor;
use Doctrine\ORM\EntityNotFoundException;
use Mautic\CoreBundle\Helper\EmailAddressHelper;
use Mautic\EmailBundle\EmailEvents;
use Mautic\EmailBundle\Entity\EmailReply;
use Mautic\EmailBundle\Entity\Stat;
use Mautic\EmailBundle\Event\EmailReplyEvent;
use Mautic\EmailBundle\Model\EmailStatModel;
use Mautic\EmailBundle\MonitoredEmail\Exception\ReplyNotFound;
use Mautic\EmailBundle\MonitoredEmail\Message;
use Mautic\EmailBundle\MonitoredEmail\Processor\Reply\Parser;
use Mautic\EmailBundle\MonitoredEmail\Search\ContactFinder;
use Mautic\LeadBundle\Model\LeadModel;
use Mautic\LeadBundle\Tracker\ContactTracker;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class Reply implements ProcessorInterface
{
public function __construct(
private EmailStatModel $emailStatModel,
private ContactFinder $contactFinder,
private LeadModel $leadModel,
private EventDispatcherInterface $dispatcher,
private LoggerInterface $logger,
private ContactTracker $contactTracker,
private EmailAddressHelper $addressHelper
) {
}
public function process(Message $message): void
{
$this->logger->debug('MONITORED EMAIL: Processing message ID '.$message->id.' for a reply');
try {
$parser = new Parser($message);
$repliedEmail = $parser->parse();
} catch (ReplyNotFound) {
// No hash found so bail as we won't consider this a reply
$this->logger->debug('MONITORED EMAIL: No hash ID found in the email body');
return;
}
$hashId = $repliedEmail->getStatHash();
$result = $this->contactFinder->findByHash($hashId);
if (!$stat = $result->getStat()) {
// No stat found so bail as we won't consider this a reply
$this->logger->debug('MONITORED EMAIL: Stat not found');
return;
}
// A stat has been found so let's compare to the From address for the contact to prevent false positives
$possibleFromEmails = $this->addressHelper->getVariations($stat->getLead()->getEmail());
$fromEmail = $this->addressHelper->cleanEmail($repliedEmail->getFromAddress());
if (!in_array($fromEmail, $possibleFromEmails)) {
// We can't reliably assume this email was from the originating contact
$this->logger->debug('MONITORED EMAIL: '.implode(', ', $possibleFromEmails).' != '.$fromEmail.' so cannot confirm match');
return;
}
$this->createReply($stat, $message->id);
$this->dispatchEvent($stat);
if (null !== $stat->getLead()) {
$this->leadModel->getRepository()->detachEntity($stat->getLead());
}
$this->emailStatModel->getRepository()->detachEntity($stat);
}
/**
* @param string $trackingHash
* @param string $messageId
*/
public function createReplyByHash($trackingHash, $messageId): void
{
/** @var Stat|null $stat */
$stat = $this->emailStatModel->getRepository()->findOneBy(['trackingHash' => $trackingHash]);
if (null === $stat) {
throw new EntityNotFoundException("Email Stat with tracking hash {$trackingHash} was not found");
}
$stat->setIsRead(true);
if (null === $stat->getDateRead()) {
$stat->setDateRead(new \DateTime());
}
$this->createReply($stat, $messageId);
$contact = $stat->getLead();
if ($contact) {
$this->dispatchEvent($stat);
}
}
/**
* @param string $messageId
*/
protected function createReply(Stat $stat, $messageId)
{
$replies = $stat->getReplies()->filter(
fn (EmailReply $reply): bool => $reply->getMessageId() === $messageId
);
if (!$replies->count()) {
$emailReply = new EmailReply($stat, $messageId);
$stat->addReply($emailReply);
$this->emailStatModel->saveEntity($stat);
}
}
private function dispatchEvent(Stat $stat): void
{
if ($this->dispatcher->hasListeners(EmailEvents::EMAIL_ON_REPLY)) {
$this->contactTracker->setTrackedContact($stat->getLead());
$event = new EmailReplyEvent($stat);
$this->dispatcher->dispatch($event, EmailEvents::EMAIL_ON_REPLY);
unset($event);
}
}
}
|