Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
a72d2e9
UserPersonalizer in CampaignProcessorMessageHandler
tatevikg1 Dec 11, 2025
d40dedd
HtmlToText
tatevikg1 Dec 11, 2025
613a196
MessageDataLoader
tatevikg1 Dec 11, 2025
759d8e0
TextParser
tatevikg1 Dec 11, 2025
d94f825
RemotePageFetcher
tatevikg1 Dec 13, 2025
3b9267f
Use repo methods
tatevikg1 Dec 14, 2025
5fc8637
Use MessagePrecacheDto
tatevikg1 Dec 14, 2025
69884a8
Refactor
tatevikg1 Dec 14, 2025
077bc63
Todo
tatevikg1 Dec 15, 2025
492e1d0
SystemMailConstructor
tatevikg1 Dec 15, 2025
109b07a
EmailBuilder
tatevikg1 Dec 16, 2025
65c0030
InjectedByHeaderSubscriber
tatevikg1 Dec 16, 2025
7e9bab2
TemplateImageManager
tatevikg1 Dec 17, 2025
3dcb90a
ExternalImageCacher
tatevikg1 Dec 17, 2025
0c5b4f4
TemplateImageEmbedder
tatevikg1 Dec 18, 2025
25ef84a
Mailer
tatevikg1 Dec 21, 2025
166a66c
RemotePageFetcherTest
tatevikg1 Dec 22, 2025
e7f9eca
TextParserTest
tatevikg1 Dec 22, 2025
cec0eb1
MessageDataLoaderTest
tatevikg1 Dec 22, 2025
2b0c256
MessageDataLoaderTest
tatevikg1 Dec 22, 2025
1643a29
Test fix
tatevikg1 Dec 22, 2025
04e84a1
Fix: phpmd
tatevikg1 Dec 23, 2025
4a9e895
Fix: phpcs
tatevikg1 Dec 24, 2025
b6e2ee2
After review 0
tatevikg1 Dec 25, 2025
ca6dc94
After review 1
tatevikg1 Dec 25, 2025
9fea466
Add tests
tatevikg1 Dec 27, 2025
2323119
EmailBuilderTest
tatevikg1 Dec 29, 2025
823e006
update coderabbit.yaml
tatevikg1 Dec 29, 2025
a140c2b
Add tests
tatevikg1 Dec 29, 2025
7f21c58
MailSizeChecker
tatevikg1 Dec 29, 2025
8342b4a
Feat/email building with attachments (#375)
TatevikGr Jan 22, 2026
39712ed
Feat: email forwarding (#377)
TatevikGr Feb 3, 2026
88e25f5
Cutoff from forward_email_period config
tatevikg1 Feb 3, 2026
6f81e7b
ForwardingResult
tatevikg1 Feb 3, 2026
2adf65c
Remove MessageFormat consts
tatevikg1 Feb 3, 2026
7adf1f6
Testing bundle
tatevikg1 Feb 3, 2026
0a9b9a4
After review 3
tatevikg1 Feb 4, 2026
ef65472
MessageDataLoader types
tatevikg1 Feb 5, 2026
d4261d0
Fix HTMLPurifier_Config
tatevikg1 Feb 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace PhpList\Core\Domain\Messaging\MessageHandler;

use Doctrine\ORM\EntityManagerInterface;
use PhpList\Core\Domain\Configuration\Service\UserPersonalizer;
use PhpList\Core\Domain\Messaging\Exception\MessageSizeLimitExceededException;
use PhpList\Core\Domain\Messaging\Message\CampaignProcessorMessage;
use PhpList\Core\Domain\Messaging\Message\SyncCampaignProcessorMessage;
Expand Down Expand Up @@ -56,6 +57,7 @@ public function __construct(
private readonly EventLogManager $eventLogManager,
private readonly MessageDataManager $messageDataManager,
private readonly MessagePrecacheService $precacheService,
private readonly UserPersonalizer $userPersonalizer,
?int $maxMailSize = null,
) {
$this->maxMailSize = $maxMailSize ?? 0;
Expand Down Expand Up @@ -159,6 +161,8 @@ private function handleEmailSending(
Message\MessageContent $precachedContent,
): void {
$processed = $this->messagePreparator->processMessageLinks($campaign->getId(), $precachedContent, $subscriber);
$processed->setText($this->userPersonalizer->personalize($processed->getText(), $subscriber->getEmail()));
$processed->setFooter($this->userPersonalizer->personalize($processed->getFooter(), $subscriber->getEmail()));
Comment thread
TatevikGr marked this conversation as resolved.
Outdated

try {
$email = $this->mailer->composeEmail($campaign, $subscriber, $processed);
Expand Down
7 changes: 1 addition & 6 deletions src/Domain/Messaging/Service/MessageProcessingPreparator.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
namespace PhpList\Core\Domain\Messaging\Service;

use PhpList\Core\Domain\Analytics\Service\LinkTrackService;
use PhpList\Core\Domain\Configuration\Service\UserPersonalizer;
use PhpList\Core\Domain\Messaging\Model\Message;
use PhpList\Core\Domain\Messaging\Model\Message\MessageContent;
use PhpList\Core\Domain\Messaging\Repository\MessageRepository;
use PhpList\Core\Domain\Subscription\Model\Subscriber;
Expand All @@ -24,7 +22,6 @@ public function __construct(
private readonly MessageRepository $messageRepository,
private readonly LinkTrackService $linkTrackService,
private readonly TranslatorInterface $translator,
private readonly UserPersonalizer $userPersonalizer,
) {
}

Expand Down Expand Up @@ -78,16 +75,14 @@ public function processMessageLinks(

$htmlText = $content->getText();
$footer = $content->getFooter();
// todo: check other configured data that should be used in mail formatting/creation
// todo: check if getTextMessage should replace links as well
if ($htmlText !== null) {
$htmlText = $this->replaceLinks($savedLinks, $htmlText);
$htmlText = $this->userPersonalizer->personalize($htmlText, $subscriber->getEmail());
$content->setText($htmlText);
}

if ($footer !== null) {
$footer = $this->replaceLinks($savedLinks, $footer);
$footer = $this->userPersonalizer->personalize($footer, $subscriber->getEmail());
$content->setFooter($footer);
}
Comment thread
TatevikGr marked this conversation as resolved.

Expand Down
21 changes: 12 additions & 9 deletions src/Domain/Messaging/Service/RateLimitedCampaignMailer.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,26 @@ public function __construct(MailerInterface $mailer, SendRateLimiter $limiter)
$this->limiter = $limiter;
}

public function composeEmail(Message $processed, Subscriber $subscriber, Message\MessageContent $content): Email
{
public function composeEmail(
Message $message,
Subscriber $subscriber,
Message\MessageContent $processedContent,
): Email {
$email = new Email();
if ($processed->getOptions()->getFromField() !== '') {
$email->from($processed->getOptions()->getFromField());
if ($message->getOptions()->getFromField() !== '') {
$email->from($message->getOptions()->getFromField());
}

if ($processed->getOptions()->getReplyTo() !== '') {
$email->replyTo($processed->getOptions()->getReplyTo());
if ($message->getOptions()->getReplyTo() !== '') {
$email->replyTo($message->getOptions()->getReplyTo());
}

return $email
->to($subscriber->getEmail())
->subject($content->getSubject())
->subject($processedContent->getSubject())
// todo: check HTML2Text functionality
->text($content->getTextMessage())
->html($content->getText());
->text($processedContent->getTextMessage())
->html($processedContent->getText());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use PhpList\Core\Domain\Configuration\Service\Manager\EventLogManager;
use PhpList\Core\Domain\Configuration\Service\UserPersonalizer;
use PhpList\Core\Domain\Messaging\Message\CampaignProcessorMessage;
use PhpList\Core\Domain\Messaging\MessageHandler\CampaignProcessorMessageHandler;
use PhpList\Core\Domain\Messaging\Model\Message;
Expand Down Expand Up @@ -57,10 +58,18 @@ protected function setUp(): void
$requeueHandler = $this->createMock(RequeueHandler::class);
$this->translator = $this->createMock(Translator::class);
$this->precacheService = $this->createMock(MessagePrecacheService::class);
$userPersonalizer = $this->createMock(UserPersonalizer::class);

$timeLimiter->method('start');
$timeLimiter->method('shouldStop')->willReturn(false);

// Ensure personalization returns original text so assertions on replaced links remain valid
$userPersonalizer
->method('personalize')
->willReturnCallback(function (string $text) {
return $text;
});

$this->handler = new CampaignProcessorMessageHandler(
mailer: $this->mailer,
entityManager: $this->entityManager,
Expand All @@ -77,6 +86,7 @@ protected function setUp(): void
eventLogManager: $this->createMock(EventLogManager::class),
messageDataManager: $this->createMock(MessageDataManager::class),
precacheService: $this->precacheService,
userPersonalizer: $userPersonalizer,
maxMailSize: 0,
);
}
Expand Down Expand Up @@ -166,6 +176,8 @@ public function testInvokeWithValidSubscriberEmail(): void
{
$campaign = $this->createMock(Message::class);
$content = $this->createContentMock();
$content->method('getText')->willReturn('<p>Test HTML message</p>');
$content->method('getFooter')->willReturn('<p>Test footer message</p>');
$campaign->method('getContent')->willReturn($content);
$metadata = $this->createMock(MessageMetadata::class);
$campaign->method('getMetadata')->willReturn($metadata);
Expand Down Expand Up @@ -225,6 +237,8 @@ public function testInvokeWithMailerException(): void
{
$campaign = $this->createMock(Message::class);
$content = $this->createContentMock();
$content->method('getText')->willReturn('<p>Test HTML message</p>');
$content->method('getFooter')->willReturn('<p>Test footer message</p>');
$metadata = $this->createMock(MessageMetadata::class);
$campaign->method('getContent')->willReturn($content);
$campaign->method('getMetadata')->willReturn($metadata);
Expand Down Expand Up @@ -278,6 +292,8 @@ public function testInvokeWithMultipleSubscribers(): void
{
$campaign = $this->createCampaignMock();
$content = $this->createContentMock();
$content->method('getText')->willReturn('<p>Test HTML message</p>');
$content->method('getFooter')->willReturn('<p>Test footer message</p>');
$metadata = $this->createMock(MessageMetadata::class);
$campaign->method('getMetadata')->willReturn($metadata);
$campaign->method('getId')->willReturn(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use PhpList\Core\Domain\Analytics\Model\LinkTrack;
use PhpList\Core\Domain\Analytics\Service\LinkTrackService;
use PhpList\Core\Domain\Configuration\Service\UserPersonalizer;
use PhpList\Core\Domain\Messaging\Model\Message\MessageContent;
use PhpList\Core\Domain\Messaging\Repository\MessageRepository;
use PhpList\Core\Domain\Messaging\Service\MessageProcessingPreparator;
Expand All @@ -23,7 +22,6 @@ class MessageProcessingPreparatorTest extends TestCase
private SubscriberRepository&MockObject $subscriberRepository;
private MessageRepository&MockObject $messageRepository;
private LinkTrackService&MockObject $linkTrackService;
private UserPersonalizer&MockObject $userPersonalizer;
private OutputInterface&MockObject $output;
private MessageProcessingPreparator $preparator;

Expand All @@ -32,21 +30,13 @@ protected function setUp(): void
$this->subscriberRepository = $this->createMock(SubscriberRepository::class);
$this->messageRepository = $this->createMock(MessageRepository::class);
$this->linkTrackService = $this->createMock(LinkTrackService::class);
$this->userPersonalizer = $this->createMock(UserPersonalizer::class);
// Ensure personalization returns original text so assertions on replaced links remain valid
$this->userPersonalizer
->method('personalize')
->willReturnCallback(function (string $text) {
return $text;
});
$this->output = $this->createMock(OutputInterface::class);

$this->preparator = new MessageProcessingPreparator(
subscriberRepository: $this->subscriberRepository,
messageRepository: $this->messageRepository,
linkTrackService: $this->linkTrackService,
translator: new Translator('en'),
userPersonalizer: $this->userPersonalizer,
);
}

Expand Down
Loading