Commit c21942c5824 for woocommerce

commit c21942c5824298254330e41c69137d1377aa6daf
Author: Tom Cafferkey <tjcafferkey@gmail.com>
Date:   Tue Nov 10 09:09:18 2026 +0000

    Prevent fatal errors when verification email is omitted (#70787)

    * Prevent fatal errors when verification email is omitted

    * Add changelog entry for email verification compatibility fix

    * Remove redundant null email verification test

    * Add debug log

    * Doing it wrong

    * wc_doing_it_wrong

    * Fix test

diff --git a/plugins/woocommerce/changelog/fix-email-verification-legacy-callers b/plugins/woocommerce/changelog/fix-email-verification-legacy-callers
new file mode 100644
index 00000000000..a76994aea76
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-email-verification-legacy-callers
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Prevent account activation crashes with extensions that verify customer emails using the legacy one-argument call.
diff --git a/plugins/woocommerce/src/Internal/CustomerEmailVerification/EmailVerificationService.php b/plugins/woocommerce/src/Internal/CustomerEmailVerification/EmailVerificationService.php
index b28c88b0c07..6647b23a408 100644
--- a/plugins/woocommerce/src/Internal/CustomerEmailVerification/EmailVerificationService.php
+++ b/plugins/woocommerce/src/Internal/CustomerEmailVerification/EmailVerificationService.php
@@ -90,18 +90,27 @@ class EmailVerificationService {
 	 * @since 11.0.0
 	 *
 	 * @param int         $user_id        WordPress user ID.
-	 * @param string|null $expected_email Email address proven by the verification flow.
+	 * @param string|null $expected_email Email address proven by the verification flow. If omitted or null, no verification is performed.
 	 * @return void
 	 */
-	public function mark_verified( int $user_id, ?string $expected_email ): void {
+	public function mark_verified( int $user_id, ?string $expected_email = null ): void {
 		if ( $this->is_verified( $user_id ) ) {
 			return;
 		}

+		if ( null === $expected_email ) {
+			wc_doing_it_wrong(
+				__METHOD__,
+				'Verification was skipped because no expected email was provided. Pass the email address proven by the verification flow as the second argument.',
+				'11.3.0'
+			);
+			return;
+		}
+
 		$account_email  = $this->get_account_email( $user_id );
-		$expected_email = null !== $expected_email ? strtolower( $expected_email ) : null;
+		$expected_email = strtolower( $expected_email );

-		if ( null === $expected_email || null === $account_email || $expected_email !== $account_email ) {
+		if ( null === $account_email || $expected_email !== $account_email ) {
 			return;
 		}

diff --git a/plugins/woocommerce/tests/php/src/Internal/CustomerEmailVerification/EmailVerificationServiceTest.php b/plugins/woocommerce/tests/php/src/Internal/CustomerEmailVerification/EmailVerificationServiceTest.php
index 19cf3bc1e88..95d8fd8e000 100644
--- a/plugins/woocommerce/tests/php/src/Internal/CustomerEmailVerification/EmailVerificationServiceTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/CustomerEmailVerification/EmailVerificationServiceTest.php
@@ -61,6 +61,22 @@ class EmailVerificationServiceTest extends WC_Unit_Test_Case {
 		remove_action( 'woocommerce_customer_email_verified', $listener );
 	}

+	/**
+	 * @testdox Legacy one-argument calls report incorrect usage without changing verification state.
+	 */
+	public function test_mark_verified_without_expected_email(): void {
+		$user_id    = wc_create_new_customer( 'legacy@example.com', 'legacyuser', 'pw' );
+		$key        = $this->sut->create_verification_key( $user_id );
+		$hook_calls = did_action( 'woocommerce_customer_email_verified' );
+
+		$this->setExpectedIncorrectUsage( EmailVerificationService::class . '::mark_verified' );
+		$this->sut->mark_verified( $user_id );
+
+		$this->assertFalse( $this->sut->is_verified( $user_id ), 'An omitted expected email must not verify the account' );
+		$this->assertTrue( $this->sut->check_verification_key( $user_id, $key ), 'An omitted expected email must not consume the pending key' );
+		$this->assertSame( $hook_calls, did_action( 'woocommerce_customer_email_verified' ), 'An omitted expected email must not fire the verification hook' );
+	}
+
 	/**
 	 * @testdox create_verification_key() returns a fresh, pending key that passes its own check.
 	 */