diff --git a/CRM/Core/BAO/UFGroup.php b/CRM/Core/BAO/UFGroup.php
index ed99596c4fee..4c75a545eb16 100644
--- a/CRM/Core/BAO/UFGroup.php
+++ b/CRM/Core/BAO/UFGroup.php
@@ -2642,41 +2642,21 @@ public static function commonSendMail($contactID, &$values) {
       return;
 
     }
-    $template = CRM_Core_Smarty::singleton();
-
-    $displayName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
-      $contactID,
-      'display_name'
-    );
-
-    self::profileDisplay($values['id'], $values['values'], $template);
     $emailList = explode(',', $values['email']);
 
-    $contactLink = CRM_Utils_System::url('civicrm/contact/view',
-      "reset=1&cid=$contactID",
-      TRUE, NULL, FALSE, FALSE, TRUE
-    );
-
     //get the default domain email address.
     [$domainEmailName, $domainEmailAddress] = CRM_Core_BAO_Domain::getNameAndEmail();
 
-    if (!$domainEmailAddress || $domainEmailAddress == 'info@EXAMPLE.ORG') {
+    if (!$domainEmailAddress || $domainEmailAddress === 'info@EXAMPLE.ORG') {
       $fixUrl = CRM_Utils_System::url('civicrm/admin/domain', 'action=update&reset=1');
       CRM_Core_Error::statusBounce(ts('The site administrator needs to enter a valid \'FROM Email Address\' in <a href="%1">Administer CiviCRM &raquo; Communications &raquo; FROM Email Addresses</a>. The email address used may need to be a valid mail account with your email service provider.', [1 => $fixUrl]));
     }
 
     foreach ($emailList as $emailTo) {
-      // FIXME: take the below out of the foreach loop
       CRM_Core_BAO_MessageTemplate::sendTemplate(
         [
-          'groupName' => 'msg_tpl_workflow_uf',
           'workflow' => 'uf_notify',
-          'contactId' => $contactID,
-          'tplParams' => [
-            'displayName' => $displayName,
-            'currentDate' => date('r'),
-            'contactLink' => $contactLink,
-          ],
+          'modelProps' => ['contactID' => $contactID, 'profileID' => $values['id'], 'profileFields' => $values['values']],
           'from' => "$domainEmailName <$domainEmailAddress>",
           'toEmail' => $emailTo,
         ]
@@ -2722,22 +2702,6 @@ public static function checkFieldsEmptyValues($gid, $cid, $params, $skipCheck =
     return NULL;
   }
 
-  /**
-   * Assign uf fields to template.
-   *
-   * @param int $gid
-   *   Group id.
-   * @param array $values
-   * @param CRM_Core_Smarty $template
-   */
-  public static function profileDisplay($gid, $values, $template) {
-    $groupTitle = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'title');
-    $template->assign('grouptitle', $groupTitle);
-    if (count($values)) {
-      $template->assign('values', $values);
-    }
-  }
-
   /**
    * Format fields for dupe Contact Matching.
    *
diff --git a/CRM/Core/WorkflowMessage/Profile/Profile.php b/CRM/Core/WorkflowMessage/Profile/Profile.php
new file mode 100644
index 000000000000..bd5427278bbf
--- /dev/null
+++ b/CRM/Core/WorkflowMessage/Profile/Profile.php
@@ -0,0 +1,74 @@
+<?php
+
+use Civi\Api4\UFField;
+use Civi\Api4\UFGroup;
+use Civi\Api4\WorkflowMessage;
+use Civi\Test;
+use Civi\WorkflowMessage\WorkflowMessageExample;
+
+/**
+ * Basic profile example.
+ *
+ * @noinspection PhpUnused
+ * @noinspection UnknownInspectionInspection
+ */
+class CRM_Core_WorkflowMessage_Profile_Profile extends WorkflowMessageExample {
+
+  /**
+   * Get the examples this class is able to deliver.
+   */
+  public function getExamples(): iterable {
+    $workflows = ['uf_notify'];
+    foreach ($workflows as $workflow) {
+      yield [
+        'name' => 'workflow/' . $workflow . '/general',
+        'title' => ts('Profile Notification'),
+        'tags' => ['preview'],
+        'workflow' => $workflow,
+      ];
+    }
+  }
+
+  /**
+   * Build an example to use when rendering the workflow.
+   *
+   * @param array $example
+   *
+   * @throws \CRM_Core_Exception
+   */
+  public function build(array &$example): void {
+    $workFlow = WorkflowMessage::get(TRUE)->addWhere('name', '=', $example['workflow'])->execute()->first();
+    $this->setWorkflowName($workFlow['name']);
+    $messageTemplate = new $workFlow['class']();
+    $this->addExampleData($messageTemplate, $example);
+    $example['data'] = $this->toArray($messageTemplate);
+  }
+
+  /**
+   * Add relevant example data.
+   *
+   * @param \CRM_Core_WorkflowMessage_UFNotify $messageTemplate
+   * @param array $example
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \Civi\API\Exception\UnauthorizedException
+   */
+  private function addExampleData(\CRM_Core_WorkflowMessage_UFNotify $messageTemplate, $example): void {
+    $contact = Test::example('entity/Contact/Barb');
+    $messageTemplate->setContact($contact);
+    $profile = UFGroup::get(FALSE)->setLimit(1)->execute()->first();
+    $fields = UFField::get(FALSE)->addWhere('id', '=', $profile['id'])->execute();
+    $values = [];
+    foreach ($fields as $field) {
+      if (isset($contact[$field['field_name']])) {
+        $values[$field['label']] = $contact[$field['field_name']];
+      }
+      else {
+        $values[$field['label']] = ts('User entered field');
+      }
+    }
+    $messageTemplate->setProfileID($profile['id']);
+    $messageTemplate->setProfileFields($values);
+  }
+
+}
diff --git a/CRM/Core/WorkflowMessage/UFNotify.php b/CRM/Core/WorkflowMessage/UFNotify.php
new file mode 100644
index 000000000000..7ae0fb13aca1
--- /dev/null
+++ b/CRM/Core/WorkflowMessage/UFNotify.php
@@ -0,0 +1,86 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+use Civi\WorkflowMessage\GenericWorkflowMessage;
+
+/**
+ * Receipt sent when someone receives a copy of profile that has been filled out.
+ *
+ * @method int getProfileID()
+ * @method $this setProfileID(int $profileID)
+ * @method array getProfileFields()
+ * @method $this setProfileFields(array $profileFields)
+ *
+ * @support template-only
+ *
+ * @see CRM_Core_BAO_UFGroup::commonSendMail
+ */
+class CRM_Core_WorkflowMessage_UFNotify extends GenericWorkflowMessage {
+  public const WORKFLOW = 'uf_notify';
+
+  /**
+   * @var int
+   *
+   * @scope tplParams
+   */
+  protected $profileID;
+
+  /**
+   * @var array
+   *
+   * @scope tplParams as values
+   */
+  protected $profileFields;
+
+  /**
+   * @var string
+   *
+   * @scope tplParams
+   */
+  protected $contactLink;
+
+  public function getContactLink(): string {
+    return CRM_Utils_System::url('civicrm/contact/view',
+      "reset=1&cid=" . $this->getContactID(),
+      TRUE, NULL, FALSE, FALSE, TRUE
+    );
+  }
+
+  /**
+   * @var string
+   *
+   * @scope tplParams as grouptitle
+   */
+  protected $groupTitle;
+
+  public function getGroupTitle(): string {
+    return CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $this->getProfileID(), 'frontend_title');
+  }
+
+  /**
+   * @var string
+   *
+   * @scope tplParams
+   */
+  protected $userDisplayName;
+
+  public function getUserDisplayName(): string {
+    $loggedInUser = CRM_Core_Session::getLoggedInContactID();
+    if (!$loggedInUser) {
+      return '';
+    }
+    return CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
+      $loggedInUser,
+      'display_name'
+    );
+  }
+
+}
diff --git a/CRM/Upgrade/Incremental/php/FiveSeventyTwo.php b/CRM/Upgrade/Incremental/php/FiveSeventyTwo.php
index b8d867a1e411..a65f15b97cc1 100644
--- a/CRM/Upgrade/Incremental/php/FiveSeventyTwo.php
+++ b/CRM/Upgrade/Incremental/php/FiveSeventyTwo.php
@@ -30,6 +30,16 @@ class CRM_Upgrade_Incremental_php_FiveSeventyTwo extends CRM_Upgrade_Incremental
   public function upgrade_5_72_alpha1($rev): void {
     $this->addTask(ts('Upgrade DB to %1: SQL', [1 => $rev]), 'runSql', $rev);
     $this->addTask('Remove localized suffixes from civicrm_mailing_group.entity_table', 'fixMailingGroupEntityTable');
+
+    $this->addTask('Replace displayName smarty token in UFNotify subject',
+      'updateMessageToken', 'uf_notify', 'ts 1=$displayName', 'ts 1=$userDisplayName', $rev
+    );
+    $this->addTask('Replace displayName smarty token in UFNotify',
+      'updateMessageToken', 'uf_notify', '$displayName', 'contact.display_name', $rev
+    );
+    $this->addTask('Replace currentDate smarty token in UFNotify',
+      'updateMessageToken', 'uf_notify', '$currentDate', 'domain.now|crmDate:"Full"', $rev
+    );
   }
 
   /**
diff --git a/xml/templates/message_templates/uf_notify_html.tpl b/xml/templates/message_templates/uf_notify_html.tpl
index 09e6b3153078..72a5bf8525a2 100644
--- a/xml/templates/message_templates/uf_notify_html.tpl
+++ b/xml/templates/message_templates/uf_notify_html.tpl
@@ -26,7 +26,7 @@
        {ts}Submitted For{/ts}
       </td>
       <td {$valueStyle}>
-       {$displayName}
+       {contact.display_name}
       </td>
      </tr>
      <tr>
@@ -34,7 +34,7 @@
        {ts}Date{/ts}
       </td>
       <td {$valueStyle}>
-       {$currentDate}
+       {domain.now|crmDate:"Full"}
       </td>
      </tr>
      <tr>
diff --git a/xml/templates/message_templates/uf_notify_subject.tpl b/xml/templates/message_templates/uf_notify_subject.tpl
index 0fd90f776aa0..fc1d4694ebbd 100644
--- a/xml/templates/message_templates/uf_notify_subject.tpl
+++ b/xml/templates/message_templates/uf_notify_subject.tpl
@@ -1 +1 @@
-{$grouptitle} {ts 1=$displayName}Submitted by %1{/ts} - {contact.display_name}
+{$grouptitle} {ts 1=$userDisplayName}Submitted by %1{/ts} - {contact.display_name}