diff --git a/src/Services/NewsletterDispatchService.php b/src/Services/NewsletterDispatchService.php index 7c62fd7..cf6fed8 100644 --- a/src/Services/NewsletterDispatchService.php +++ b/src/Services/NewsletterDispatchService.php @@ -152,9 +152,20 @@ final class NewsletterDispatchService // The intro paragraph is attributed to the tree contact user // (the same person we use as Reply-To). If they're linked to an // Individual record we fold their avatar into the embed set so - // the editorial block can render with their face on the left, - // matching the styling of the event cards below. - $intro_author = $this->resolveIntroAuthor($tree, $reply_to); + // the editorial block can render with their face on the left. + // We only bother when at least one locale actually has an intro + // to send — otherwise loading/encoding the portrait is wasted + // work and the bytes would be attached to every recipient's + // email without ever being referenced. + $has_any_intro = false; + foreach (array_keys(Configuration::supportedSubjectLocales()) as $code) { + if (trim(Configuration::introForLocale($module, $tree, $code)) !== '') { + $has_any_intro = true; + break; + } + } + + $intro_author = $has_any_intro ? $this->resolveIntroAuthor($tree, $reply_to) : null; if ($intro_author instanceof Individual && !isset($avatars[$this->avatarCidName($intro_author->xref())])) { $author_avatar = $this->resolveAvatar($intro_author); @@ -213,19 +224,6 @@ final class NewsletterDispatchService $this->avatarKeysForXrefs(array_keys($detailed_set)), ); - // The intro author sits outside the detailed set — - // make sure their avatar bytes still ride along so - // the editorial portrait renders inline instead of - // showing a broken image (which we'd otherwise hide - // behind a tree-page login link). - if ($intro_author instanceof Individual) { - $author_cid = $this->avatarCidName($intro_author->xref()); - - if (isset($avatars[$author_cid])) { - $recipient_avatars[$author_cid] = $avatars[$author_cid]; - } - } - // Decide whether to attach the intro for *this* // recipient: only if it's non-empty AND this // recipient hasn't yet received the current @@ -237,6 +235,17 @@ final class NewsletterDispatchService : $external_seen; $show_intro = $intro !== '' && $intro_version > $recipient_seen; + // Only attach the editorial portrait to recipients + // who actually see the intro — otherwise the bytes + // would ride along uselessly and bloat the message. + if ($show_intro && $intro_author instanceof Individual) { + $author_cid = $this->avatarCidName($intro_author->xref()); + + if (isset($avatars[$author_cid])) { + $recipient_avatars[$author_cid] = $avatars[$author_cid]; + } + } + $personalised_intro = $show_intro ? $this->renderIntroTemplate($intro, $recipient) : '';