Commit 587e995ae6f for woocommerce

commit 587e995ae6fac3f3f4dda18ac7d6297966585e97
Author: Marco Almeida | Webdados <webdados@users.noreply.github.com>
Date:   Wed May 27 15:00:29 2026 +0100

    Use first name for greeting if available, instead of user login, on new customer account and reset password emails (#65270)

diff --git a/plugins/woocommerce/changelog/65269-first-name-greeting-customer-emails b/plugins/woocommerce/changelog/65269-first-name-greeting-customer-emails
new file mode 100644
index 00000000000..82c66c58bbb
--- /dev/null
+++ b/plugins/woocommerce/changelog/65269-first-name-greeting-customer-emails
@@ -0,0 +1,4 @@
+Significance: minor
+Type: enhancement
+
+Use the customer's first name (billing first name, falling back to WordPress first name, then username) in the greeting of the new account and reset password emails.
diff --git a/plugins/woocommerce/includes/emails/class-wc-email-customer-new-account.php b/plugins/woocommerce/includes/emails/class-wc-email-customer-new-account.php
index 763393920dc..02a16b85aae 100644
--- a/plugins/woocommerce/includes/emails/class-wc-email-customer-new-account.php
+++ b/plugins/woocommerce/includes/emails/class-wc-email-customer-new-account.php
@@ -58,6 +58,13 @@ if ( ! class_exists( 'WC_Email_Customer_New_Account', false ) ) {
 		 */
 		public $set_password_url;

+		/**
+		 * User display name (first name, or login as fallback).
+		 *
+		 * @var string
+		 */
+		public $user_display_name;
+
 		/**
 		 * Constructor.
 		 */
@@ -113,6 +120,9 @@ if ( ! class_exists( 'WC_Email_Customer_New_Account', false ) ) {
 				$this->set_password_url   = $this->generate_set_password_url();
 				$this->user_login         = stripslashes( $this->object->user_login );
 				$this->user_email         = stripslashes( $this->object->user_email );
+				$customer                 = new WC_Customer( $user_id );
+				$first_name               = ! empty( $customer->get_billing_first_name() ) ? $customer->get_billing_first_name() : $this->object->first_name;
+				$this->user_display_name  = ! empty( $first_name ) ? $first_name : $this->user_login;
 				$this->recipient          = $this->user_email;
 				$this->user_pass          = $user_pass;
 				$this->password_generated = $password_generated;
@@ -135,6 +145,7 @@ if ( ! class_exists( 'WC_Email_Customer_New_Account', false ) ) {
 					'email_heading'      => $this->get_heading(),
 					'additional_content' => $this->get_additional_content(),
 					'user_login'         => $this->user_login,
+					'user_display_name'  => $this->user_display_name,
 					'blogname'           => $this->get_blogname(),
 					'set_password_url'   => $this->set_password_url,
 					'sent_to_admin'      => false,
@@ -158,6 +169,7 @@ if ( ! class_exists( 'WC_Email_Customer_New_Account', false ) ) {
 					'email_heading'      => $this->get_heading(),
 					'additional_content' => $this->get_additional_content(),
 					'user_login'         => $this->user_login,
+					'user_display_name'  => $this->user_display_name,
 					'blogname'           => $this->get_blogname(),
 					'set_password_url'   => $this->set_password_url,
 					'sent_to_admin'      => false,
@@ -179,6 +191,7 @@ if ( ! class_exists( 'WC_Email_Customer_New_Account', false ) ) {
 				$this->template_block_content,
 				array(
 					'user_login'         => $this->user_login,
+					'user_display_name'  => $this->user_display_name,
 					'set_password_url'   => $this->set_password_url,
 					'sent_to_admin'      => false,
 					'plain_text'         => false,
diff --git a/plugins/woocommerce/includes/emails/class-wc-email-customer-reset-password.php b/plugins/woocommerce/includes/emails/class-wc-email-customer-reset-password.php
index 32452c55694..670012a2d17 100644
--- a/plugins/woocommerce/includes/emails/class-wc-email-customer-reset-password.php
+++ b/plugins/woocommerce/includes/emails/class-wc-email-customer-reset-password.php
@@ -51,6 +51,13 @@ if ( ! class_exists( 'WC_Email_Customer_Reset_Password', false ) ) :
 		 */
 		public $reset_key;

+		/**
+		 * User display name (first name, or login as fallback).
+		 *
+		 * @var string
+		 */
+		public $user_display_name;
+
 		/**
 		 * Constructor.
 		 */
@@ -114,12 +121,19 @@ if ( ! class_exists( 'WC_Email_Customer_Reset_Password', false ) ) :
 			$this->setup_locale();

 			if ( $user_login && $reset_key ) {
-				$this->object     = get_user_by( 'login', $user_login );
-				$this->user_id    = $this->object->ID;
-				$this->user_login = $user_login;
-				$this->reset_key  = $reset_key;
-				$this->user_email = stripslashes( $this->object->user_email );
-				$this->recipient  = $this->user_email;
+				$this->object = get_user_by( 'login', $user_login );
+				if ( ! $this->object ) {
+					$this->restore_locale();
+					return;
+				}
+				$this->user_id           = $this->object->ID;
+				$this->user_login        = $user_login;
+				$this->reset_key         = $reset_key;
+				$this->user_email        = stripslashes( $this->object->user_email );
+				$this->recipient         = $this->user_email;
+				$customer                = new WC_Customer( $this->object->ID );
+				$first_name              = ! empty( $customer->get_billing_first_name() ) ? $customer->get_billing_first_name() : $this->object->first_name;
+				$this->user_display_name = ! empty( $first_name ) ? $first_name : $this->user_login;
 			}

 			$this->send_notification();
@@ -139,6 +153,7 @@ if ( ! class_exists( 'WC_Email_Customer_Reset_Password', false ) ) :
 					'email_heading'      => $this->get_heading(),
 					'user_id'            => $this->user_id,
 					'user_login'         => $this->user_login,
+					'user_display_name'  => $this->user_display_name,
 					'reset_key'          => $this->reset_key,
 					'blogname'           => $this->get_blogname(),
 					'additional_content' => $this->get_additional_content(),
@@ -161,6 +176,7 @@ if ( ! class_exists( 'WC_Email_Customer_Reset_Password', false ) ) :
 					'email_heading'      => $this->get_heading(),
 					'user_id'            => $this->user_id,
 					'user_login'         => $this->user_login,
+					'user_display_name'  => $this->user_display_name,
 					'reset_key'          => $this->reset_key,
 					'blogname'           => $this->get_blogname(),
 					'additional_content' => $this->get_additional_content(),
@@ -181,12 +197,13 @@ if ( ! class_exists( 'WC_Email_Customer_Reset_Password', false ) ) :
 			return wc_get_template_html(
 				$this->template_block_content,
 				array(
-					'user_id'       => $this->user_id,
-					'user_login'    => $this->user_login,
-					'reset_key'     => $this->reset_key,
-					'sent_to_admin' => false,
-					'plain_text'    => false,
-					'email'         => $this,
+					'user_id'           => $this->user_id,
+					'user_login'        => $this->user_login,
+					'user_display_name' => $this->user_display_name,
+					'reset_key'         => $this->reset_key,
+					'sent_to_admin'     => false,
+					'plain_text'        => false,
+					'email'             => $this,
 				)
 			);
 		}
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index ef06eb24cd2..b3164926d6e 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -19044,18 +19044,6 @@ parameters:
 			count: 1
 			path: includes/emails/class-wc-email-customer-refunded-order.php

-		-
-			message: '#^Cannot access property \$ID on WP_User\|false\.$#'
-			identifier: property.nonObject
-			count: 1
-			path: includes/emails/class-wc-email-customer-reset-password.php
-
-		-
-			message: '#^Cannot access property \$user_email on WP_User\|false\.$#'
-			identifier: property.nonObject
-			count: 1
-			path: includes/emails/class-wc-email-customer-reset-password.php
-
 		-
 			message: '#^Method WC_Email_Customer_Reset_Password\:\:trigger\(\) has no return type specified\.$#'
 			identifier: missingType.return
diff --git a/plugins/woocommerce/templates/emails/customer-new-account.php b/plugins/woocommerce/templates/emails/customer-new-account.php
index 5d1a56f7b37..054996583d6 100644
--- a/plugins/woocommerce/templates/emails/customer-new-account.php
+++ b/plugins/woocommerce/templates/emails/customer-new-account.php
@@ -12,7 +12,7 @@
  *
  * @see https://woocommerce.com/document/template-structure/
  * @package WooCommerce\Templates\Emails
- * @version 10.4.0
+ * @version 10.9.0
  */

 use Automattic\WooCommerce\Utilities\FeaturesUtil;
@@ -31,8 +31,8 @@ $email_improvements_enabled = FeaturesUtil::feature_is_enabled( 'email_improveme
 do_action( 'woocommerce_email_header', $email_heading, $email ); ?>

 <?php echo $email_improvements_enabled ? '<div class="email-introduction">' : ''; ?>
-<?php /* translators: %s: Customer username */ ?>
-<p><?php printf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $user_login ) ); ?></p>
+<?php /* translators: %s: Customer first name, or username if name is not available */ ?>
+<p><?php printf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $user_display_name ) ); ?></p>
 <?php if ( $email_improvements_enabled ) : ?>
 	<?php /* translators: %s: Site title */ ?>
 	<p><?php printf( esc_html__( 'Thanks for creating an account on %s. Here’s a copy of your user details.', 'woocommerce' ), esc_html( $blogname ) ); ?></p>
diff --git a/plugins/woocommerce/templates/emails/customer-reset-password.php b/plugins/woocommerce/templates/emails/customer-reset-password.php
index 158ad5521a9..12c861a6711 100644
--- a/plugins/woocommerce/templates/emails/customer-reset-password.php
+++ b/plugins/woocommerce/templates/emails/customer-reset-password.php
@@ -12,7 +12,7 @@
  *
  * @see https://woocommerce.com/document/template-structure/
  * @package WooCommerce\Templates\Emails
- * @version 10.4.0
+ * @version 10.9.0
  */

 use Automattic\WooCommerce\Utilities\FeaturesUtil;
@@ -28,8 +28,8 @@ $email_improvements_enabled = FeaturesUtil::feature_is_enabled( 'email_improveme
 <?php do_action( 'woocommerce_email_header', $email_heading, $email ); ?>

 <?php echo $email_improvements_enabled ? '<div class="email-introduction">' : ''; ?>
-<?php /* translators: %s: Customer username */ ?>
-<p><?php printf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $user_login ) ); ?></p>
+<?php /* translators: %s: Customer first name, or username if name is not available */ ?>
+<p><?php printf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $user_display_name ) ); ?></p>
 <?php /* translators: %s: Store name */ ?>
 <p><?php printf( esc_html__( 'Someone has requested a new password for the following account on %s:', 'woocommerce' ), esc_html( $blogname ) ); ?></p>
 <?php if ( $email_improvements_enabled ) : ?>
diff --git a/plugins/woocommerce/templates/emails/plain/customer-new-account.php b/plugins/woocommerce/templates/emails/plain/customer-new-account.php
index 28fc818133b..011e292d675 100644
--- a/plugins/woocommerce/templates/emails/plain/customer-new-account.php
+++ b/plugins/woocommerce/templates/emails/plain/customer-new-account.php
@@ -12,7 +12,7 @@
  *
  * @see https://woocommerce.com/document/template-structure/
  * @package WooCommerce\Templates\Emails\Plain
- * @version 10.0.0
+ * @version 10.9.0
  */

 use Automattic\WooCommerce\Utilities\FeaturesUtil;
@@ -25,8 +25,8 @@ echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n";
 echo esc_html( wp_strip_all_tags( $email_heading ) );
 echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n";

-/* translators: %s: Customer username */
-echo sprintf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $user_login ) ) . "\n\n";
+/* translators: %s: Customer first name, or username if name is not available */
+echo sprintf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $user_display_name ) ) . "\n\n";
 if ( $email_improvements_enabled ) {
 	/* translators: %s: Site title */
 	echo sprintf( esc_html__( 'Thanks for creating an account on %s. Here’s a copy of your user details.', 'woocommerce' ), esc_html( $blogname ) ) . "\n\n";
diff --git a/plugins/woocommerce/templates/emails/plain/customer-reset-password.php b/plugins/woocommerce/templates/emails/plain/customer-reset-password.php
index c28627c3d77..6534b532803 100644
--- a/plugins/woocommerce/templates/emails/plain/customer-reset-password.php
+++ b/plugins/woocommerce/templates/emails/plain/customer-reset-password.php
@@ -12,7 +12,7 @@
  *
  * @see https://woocommerce.com/document/template-structure/
  * @package WooCommerce\Templates\Emails\Plain
- * @version 9.8.0
+ * @version 10.9.0
  */

 use Automattic\WooCommerce\Utilities\FeaturesUtil;
@@ -25,8 +25,8 @@ echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n";
 echo esc_html( wp_strip_all_tags( $email_heading ) );
 echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n";

-/* translators: %s: Customer username */
-echo sprintf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $user_login ) ) . "\n\n";
+/* translators: %s: Customer first name, or username if name is not available */
+echo sprintf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $user_display_name ) ) . "\n\n";
 /* translators: %s: Store name */
 echo sprintf( esc_html__( 'Someone has requested a new password for the following account on %s:', 'woocommerce' ), esc_html( $blogname ) ) . "\n\n";
 if ( $email_improvements_enabled ) {