44
55namespace PhpList \Core \Domain \Messaging \MessageHandler ;
66
7+ use DateTime ;
8+ use DateTimeImmutable ;
9+ use Doctrine \DBAL \Exception \UniqueConstraintViolationException ;
710use Doctrine \ORM \EntityManagerInterface ;
811use PhpList \Core \Domain \Configuration \Service \UserPersonalizer ;
912use PhpList \Core \Domain \Messaging \Exception \MessageSizeLimitExceededException ;
1316use PhpList \Core \Domain \Messaging \Model \Message ;
1417use PhpList \Core \Domain \Messaging \Model \Message \MessageStatus ;
1518use PhpList \Core \Domain \Messaging \Model \Message \UserMessageStatus ;
19+ use PhpList \Core \Domain \Messaging \Model \MessageData ;
1620use PhpList \Core \Domain \Messaging \Model \UserMessage ;
1721use PhpList \Core \Domain \Messaging \Repository \MessageRepository ;
1822use PhpList \Core \Domain \Messaging \Repository \UserMessageRepository ;
23+ use PhpList \Core \Domain \Messaging \Service \Builder \EmailBuilder ;
1924use PhpList \Core \Domain \Messaging \Service \Handler \RequeueHandler ;
2025use PhpList \Core \Domain \Messaging \Service \Manager \MessageDataManager ;
2126use PhpList \Core \Domain \Messaging \Service \MaxProcessTimeLimiter ;
2934use PhpList \Core \Domain \Subscription \Service \Provider \SubscriberProvider ;
3035use Psr \Log \LoggerInterface ;
3136use Psr \SimpleCache \CacheInterface ;
37+ use Symfony \Component \Mailer \Envelope ;
38+ use Symfony \Component \Mailer \MailerInterface ;
3239use Symfony \Component \Messenger \Attribute \AsMessageHandler ;
40+ use Symfony \Component \Mime \Address ;
3341use Symfony \Component \Mime \Email ;
3442use Symfony \Contracts \Translation \TranslatorInterface ;
3543use Throwable ;
@@ -44,7 +52,8 @@ class CampaignProcessorMessageHandler
4452 private ?int $ maxMailSize ;
4553
4654 public function __construct (
47- private readonly RateLimitedCampaignMailer $ mailer ,
55+ private readonly MailerInterface $ mailer ,
56+ private readonly RateLimitedCampaignMailer $ rateLimitedCampaignMailer ,
4857 private readonly EntityManagerInterface $ entityManager ,
4958 private readonly SubscriberProvider $ subscriberProvider ,
5059 private readonly MessageProcessingPreparator $ messagePreparator ,
@@ -61,6 +70,8 @@ public function __construct(
6170 private readonly MessagePrecacheService $ precacheService ,
6271 private readonly UserPersonalizer $ userPersonalizer ,
6372 private readonly MessageDataLoader $ messageDataLoader ,
73+ private readonly EmailBuilder $ emailBuilder ,
74+ private readonly string $ messageEnvelope ,
6475 ?int $ maxMailSize = null ,
6576 ) {
6677 $ this ->maxMailSize = $ maxMailSize ?? 0 ;
@@ -99,18 +110,71 @@ public function __invoke(CampaignProcessorMessage|SyncCampaignProcessorMessage $
99110// $userSelection = $loadedMessageData['userselection'];
100111
101112 $ cacheKey = sprintf ('messaging.message.base.%d ' , $ campaign ->getId ());
102- $ messagePrecached = $ this ->precacheService ->precacheMessage ($ campaign , $ loadedMessageData );
103- if (!$ messagePrecached ) {
113+ if (!$ this ->precacheService ->precacheMessage ($ campaign , $ loadedMessageData )) {
104114 $ this ->updateMessageStatus ($ campaign , MessageStatus::Suspended);
105115
106116 return ;
107117 }
108118
119+ if (!empty ($ loadedMessageData ['notify_start ' ]) && !isset ($ loadedMessageData ['start_notified ' ])) {
120+ $ notifications = explode (', ' , $ loadedMessageData ['notify_start ' ]);
121+ foreach ($ notifications as $ notification ) {
122+ $ email = $ this ->emailBuilder ->buildPhplistEmail (
123+ messageId: $ campaign ->getId (),
124+ to: $ notification ,
125+ subject: $ this ->translator ->trans ('Campaign started ' ),
126+ message: $ this ->translator ->trans (
127+ 'phplist has started sending the campaign with subject %s ' ,
128+ $ loadedMessageData ['subject ' ]
129+ ),
130+ inBlast: false ,
131+ );
132+
133+ // todo: check if from name should be from config
134+ $ envelope = new Envelope (
135+ sender: new Address ($ this ->messageEnvelope , 'PHPList ' ),
136+ recipients: [new Address ($ email ->getTo ()[0 ]->getAddress ())],
137+ );
138+ $ this ->mailer ->send (message: $ email , envelope: $ envelope );
139+ }
140+ $ messageData = new MessageData ();
141+ $ messageData ->setName ('start_notified ' );
142+ $ messageData ->setId ($ message ->getMessageId ());
143+ $ messageData ->setData ((new DateTimeImmutable ())->format ('Y-m-d H:i:s ' ));
144+
145+ try {
146+ $ this ->entityManager ->persist ($ messageData );
147+ $ this ->entityManager ->flush ();
148+ } catch (UniqueConstraintViolationException $ e ) {
149+ // equivalent to IGNORE — do nothing
150+ }
151+ }
152+
109153 $ this ->updateMessageStatus ($ campaign , MessageStatus::Prepared);
110154 $ subscribers = $ this ->subscriberProvider ->getSubscribersForMessage ($ campaign );
111155
112156 $ this ->updateMessageStatus ($ campaign , MessageStatus::InProcess);
113157
158+ // if (USE_LIST_EXCLUDE) {
159+ // if (VERBOSE) {
160+ // processQueueOutput(s('looking for users who can be excluded from this mailing'));
161+ // }
162+ // if (count($msgdata['excludelist'])) {
163+ // $query
164+ // = ' select userid'
165+ // .' from '.$GLOBALS['tables']['listuser']
166+ // .' where listid in ('.implode(',', $msgdata['excludelist']).')';
167+ // if (VERBOSE) {
168+ // processQueueOutput('Exclude query '.$query);
169+ // }
170+ // $req = Sql_Query($query);
171+ // while ($row = Sql_Fetch_Row($req)) {
172+ // $um = Sql_Query(sprintf('replace into %s (entered,userid,messageid,status) values(now(),%d,%d,"excluded")',
173+ // $tables['usermessage'], $row[0], $messageid));
174+ // }
175+ // }
176+ // }
177+
114178 $ this ->timeLimiter ->start ();
115179 $ stoppedEarly = false ;
116180
@@ -157,6 +221,9 @@ private function unconfirmSubscriber(Subscriber $subscriber): void
157221
158222 private function updateMessageStatus (Message $ message , MessageStatus $ status ): void
159223 {
224+ if ($ status === MessageStatus::InProcess && $ message ->getMetadata ()->getSendStart () === null ) {
225+ $ message ->getMetadata ()->setSendStart (new DateTime ());
226+ }
160227 $ message ->getMetadata ()->setStatus ($ status );
161228 $ this ->entityManager ->flush ();
162229 }
@@ -195,7 +262,7 @@ private function handleEmailSending(
195262 $ processed ->footer = $ this ->userPersonalizer ->personalize ($ processed ->footer , $ subscriber ->getEmail ());
196263
197264 try {
198- $ email = $ this ->mailer ->composeEmail ($ campaign , $ subscriber , $ processed );
265+ $ email = $ this ->rateLimitedCampaignMailer ->composeEmail ($ campaign , $ subscriber , $ processed );
199266 $ this ->mailer ->send ($ email );
200267 $ this ->checkMessageSizeOrSuspendCampaign ($ campaign , $ email , $ subscriber ->hasHtmlEmail ());
201268 $ this ->updateUserMessageStatus ($ userMessage , UserMessageStatus::Sent);
0 commit comments