E-mail sent from siteMethod called in `page.update:after` hook uses old instead of the updated data

I got another question regarding hooks :smiley:

When I trigger the sending of an e-mail from a page.update:after hook the e-mail always contains the old field values instead of the updated ones.

I send the e-mail from a custom siteMethod which fetches some of the page data for the e-mail text.

But since I’m calling this method from the update:after hook and even pass the $newPage reference,
where does the old data come from?

Can you share the code, so we can see better what is going on?

of course @jimbobrjames :grin:

The simplified hook:

'page.update:after' => function ($newPage, $oldPage) {
  if($newPage->intendedTemplate() == 'termin') {
    // check if it makes sense to send an e-mail at all
    and $newPage->inFuture()
    and $newPage->participantCount() > 0) {
      // date or address have changed
      if($oldPage->date()->value() != $newPage->date()->value()
      or $oldPage->address()->value() != $newPage->address()->value()) {
        // e-mails to all participants of this event (skipped the fetching of participants and their booking)
        foreach($participants as $participant) {
          $this->site()->sendCustomEmail('termin-aenderung', $participant['email'], $newPage->autoid(), $participant['name']);

And the very simplified siteMethod:

'sendCustomEmail' => function($template = '', $to = '', $event_id = false, $name = '') {
  // e-mail template is valid and recipient not empty
  if ($template = $this->find('email/'.$template)
  and $to != '') {
    // check event_id and get event page object
    if ($event_id != false
    and $event = $event_id->fromAutoId()) {
      // generate e-mail-texts
      $text = snippet('email-header-text', [], true).'Hi '.$name.",\r\n".$template->specific_text()."\r\n".$event->date()->toDate('d.m.Y')."\r\n".$event->address().snippet('email-footer-text', [], true);
      $html = snippet('email-header-html', [], true).'<p>Hi '.$name.',</p><p>'.$template->specific_text().'</p><p>'.$event->date()->toDate('d.m.Y').'</p><p>'.$event->address().'</p>'.snippet('email-footer-html', [], true);
      try {
          'to'         => $to,
          'replyTo'    => '...',
          'from'       => '...',
          'subject'    => $template->subject()->value().' - "'.$event->title().'"',
          'template'   => 'custom-template',
          'data'       => [
            'textmessage' => $text,
            'htmlmessage' => $html,
      } catch(Exception $error) {
        return $error->getMessage();

Thanks for having a look!

You are getting the page from it’s auto id. Maybe the problem is in that plugin.

A way around it could be to pass the &newPage Object directly to the email method. This is also a performance optimisazion because in your code the page data is loaded for every single participant.

1 Like

Arghh… why I didn’t think about that here… :man_facepalming:
You are absolutely right! Thanks a lot @moeli!

I use autoID to ensure nothing breaks in the relation between events (i.e. an event slug changes or this kind of stuff and need it at some points) but of course it makes no sense to use this here since I have the correct page object already at hand :sweat_smile:

Now the e-mails contain the updated data (and is a little faster too) :slight_smile: