diff --git a/.github/oxid-esales/shop_ce.yaml b/.github/oxid-esales/shop_ce.yaml
index c953dfa00f..ee021e4549 100644
--- a/.github/oxid-esales/shop_ce.yaml
+++ b/.github/oxid-esales/shop_ce.yaml
@@ -4,6 +4,8 @@
 install: &install
   git:
     sdk_ref: b-8.0.x
+    ref: &ref 'b-8.0.x-fix-duplicate-email-error-OXDEV-8351'
+    shop_ref: *ref
   add_services: 'selenium-chrome-126'
   method: script
   script: 'source/.github/oxid-esales/install.sh'
diff --git a/composer.json b/composer.json
index 631a0903ff..356e896c54 100644
--- a/composer.json
+++ b/composer.json
@@ -51,7 +51,7 @@
         "incenteev/composer-parameter-handler": "^2.1.4",
         "mikey179/vfsstream": "~1.6.8",
         "oxid-esales/codeception-modules": "dev-b-8.0.x",
-        "oxid-esales/codeception-page-objects": "dev-b-8.0.x",
+        "oxid-esales/codeception-page-objects": "dev-b-8.0.x-fix-duplicate-email-error-OXDEV-8351",
         "oxid-esales/developer-tools": "dev-b-8.0.x",
         "oxid-esales/oxideshop-ide-helper": "dev-b-8.0.x",
         "phpspec/prophecy-phpunit": "^2.0.1",
diff --git a/source/Application/Component/UserComponent.php b/source/Application/Component/UserComponent.php
index a69a18bb9e..df31adfd6d 100644
--- a/source/Application/Component/UserComponent.php
+++ b/source/Application/Component/UserComponent.php
@@ -643,59 +643,60 @@ protected function changeUserWithoutRedirect()
         if (!$user) {
             return;
         }
+
+        $currentEmail = $user->getFieldData('oxusername');
+        $password = $user->getFieldData('oxpassword');
         $shippingAddress = $this->getShippingAddress();
         $billingAddress = $this->getBillingAddress();
+        $newEmail = $billingAddress['oxuser__oxusername'] ?? '';
 
-        $username = $user->getFieldData('oxusername');
-        $password = $user->getFieldData('oxpassword');
         try {
-            $newName = $billingAddress['oxuser__oxusername'] ?? '';
+            $isUsernameUpdated = $this->isUserNameUpdated($currentEmail ?? '', $newEmail);
+            if ($isUsernameUpdated && $this->isGuestUser($user)) {
+                $this->deleteExistingGuestUser($newEmail);
+            }
             if (
-                $this->isGuestUser($user)
-                && $this->isUserNameUpdated($user->oxuser__oxusername->value ?? '', $newName)
+                !$this->isGuestUser($user)
+                && $isUsernameUpdated
+                && $user->isEmailInUse($newEmail)
             ) {
-                $this->deleteExistingGuestUser($newName);
+                Registry::getUtilsView()->addErrorToDisplay('ERROR_MESSAGE_USER_USEREXISTS');
+                return false;
             }
-            $user->changeUserData($username, $password, $password, $billingAddress, $shippingAddress);
+            $user->changeUserData($currentEmail, $password, $password, $billingAddress, $shippingAddress);
 
             $isSubscriptionRequested = Registry::getRequest()->getRequestEscapedParameter('blnewssubscribed');
-            $userSubscriptionStatus = $isSubscriptionRequested
-                ?? $user->getNewsSubscription()->getOptInStatus();
-            // check if email address changed, if so, force check newsletter subscription settings.
-            $billingUsername = $billingAddress['oxuser__oxusername'] ?? null;
-            $forceSubscriptionCheck = ($billingUsername !== null && $billingUsername !== $username);
+            $userSubscriptionStatus = $isSubscriptionRequested ?? $user->getNewsSubscription()->getOptInStatus();
             $isSubscriptionEmailRequested = Registry::getConfig()->getConfigParam('blOrderOptInEmail');
+
             $this->_blNewsSubscriptionStatus = $user->setNewsSubscription(
                 $userSubscriptionStatus,
                 $isSubscriptionEmailRequested,
-                $forceSubscriptionCheck
+                $isUsernameUpdated
             );
+
+            $this->resetPermissions();
+
+            $orderRemark = Registry::getRequest()->getRequestParameter('order_remark', true);
+            if ($orderRemark) {
+                $session->setVariable('ordrem', $orderRemark);
+            } else {
+                $session->deleteVariable('ordrem');
+            }
+
+            if ($basket = $session->getBasket()) {
+                $basket->setBasketUser(null);
+                $basket->onUpdate();
+            }
+
+            return true;
         } catch (UserException | ConnectionException | InputException $exception) {
             Registry::getUtilsView()->addErrorToDisplay($exception, false, true);
-
             return;
         } catch (\Throwable) {
             Registry::getUtilsView()->addErrorToDisplay('ERROR_MESSAGE_USER_UPDATE_FAILED', false, true);
             return false;
         }
-
-        $this->resetPermissions();
-
-        // order remark
-        $orderRemark = Registry::getRequest()->getRequestParameter('order_remark', true);
-
-        if ($orderRemark) {
-            $session->setVariable('ordrem', $orderRemark);
-        } else {
-            $session->deleteVariable('ordrem');
-        }
-
-        if ($basket = $session->getBasket()) {
-            $basket->setBasketUser(null);
-            $basket->onUpdate();
-        }
-
-        return true;
     }
 
     /**
diff --git a/source/Application/Controller/Admin/UserMain.php b/source/Application/Controller/Admin/UserMain.php
index 6dd0e5c005..c199c85900 100644
--- a/source/Application/Controller/Admin/UserMain.php
+++ b/source/Application/Controller/Admin/UserMain.php
@@ -7,6 +7,7 @@
 
 namespace OxidEsales\EshopCommunity\Application\Controller\Admin;
 
+use OxidEsales\Eshop\Application\Model\User;
 use OxidEsales\Eshop\Core\Registry;
 use stdClass;
 use Exception;
@@ -26,7 +27,7 @@ public function render()
         parent::render();
 
         // malladmin stuff
-        $oAuthUser = oxNew(\OxidEsales\Eshop\Application\Model\User::class);
+        $oAuthUser = oxNew(User::class);
         $oAuthUser->loadAdminUser();
         $blisMallAdmin = $oAuthUser->oxuser__oxrights->value == "malladmin";
 
@@ -52,7 +53,7 @@ public function render()
         $soxId = $this->_aViewData["oxid"] = $this->getEditObjectId();
         if (isset($soxId) && $soxId != "-1") {
             // load object
-            $oUser = oxNew(\OxidEsales\Eshop\Application\Model\User::class);
+            $oUser = oxNew(User::class);
             $oUser->load($soxId);
             $this->_aViewData["edit"] = $oUser;
 
@@ -102,31 +103,30 @@ public function save()
     {
         parent::save();
 
-        //allow admin information edit only for MALL admins
         $soxId = $this->getEditObjectId();
         if ($this->allowAdminEdit($soxId)) {
             $aParams = Registry::getRequest()->getRequestEscapedParameter("editval");
 
-            // checkbox handling
             if (!isset($aParams['oxuser__oxactive'])) {
                 $aParams['oxuser__oxactive'] = 0;
             }
 
-            $oUser = oxNew(\OxidEsales\Eshop\Application\Model\User::class);
+            $oUser = oxNew(User::class);
             if ($soxId != "-1") {
                 $oUser->load($soxId);
             } else {
                 $aParams['oxuser__oxid'] = null;
             }
 
-            //setting new password
             if (($sNewPass = Registry::getRequest()->getRequestEscapedParameter("newPassword"))) {
                 $oUser->setPassword($sNewPass);
             }
 
-            //FS#2167 V checks for already used email
-
-            if (isset($aParams['oxuser__oxusername']) && $oUser->checkIfEmailExists($aParams['oxuser__oxusername'])) {
+            if (
+                isset($aParams['oxuser__oxusername'])
+                && ($aParams['oxuser__oxusername'] !== $oUser->getRawFieldData('oxusername'))
+                && $oUser->isEmailInUse($aParams['oxuser__oxusername'])
+            ) {
                 $this->_sSaveError = 'EXCEPTION_USER_USEREXISTS';
 
                 return;
@@ -134,18 +134,15 @@ public function save()
 
             $oUser->assign($aParams);
 
-            //seting shop id for ONLY for new created user
             if ($soxId == "-1") {
                 $this->onUserCreation($oUser);
             }
 
-            // A. changing field type to save birth date correctly
             $oUser->oxuser__oxbirthdate->fldtype = 'char';
 
             try {
                 $oUser->save();
 
-                // set oxid if inserted
                 $this->setEditObjectId($oUser->getId());
             } catch (Exception $oExcp) {
                 $this->_sSaveError = $oExcp->getMessage();
@@ -168,9 +165,9 @@ protected function calculateAdditionalRights($userRights)
     /**
      * Additional actions on user creation.
      *
-     * @param \OxidEsales\Eshop\Application\Model\User $user
+     * @param User $user
      *
-     * @return \OxidEsales\Eshop\Application\Model\User
+     * @return User
      */
     protected function onUserCreation($user)
     {
diff --git a/source/Application/Model/User.php b/source/Application/Model/User.php
index b953347aa1..9dc9edf008 100644
--- a/source/Application/Model/User.php
+++ b/source/Application/Model/User.php
@@ -20,6 +20,7 @@
 use OxidEsales\EshopCommunity\Core\Di\ContainerFacade;
 use OxidEsales\EshopCommunity\Internal\Domain\Authentication\Bridge\PasswordServiceBridgeInterface;
 use OxidEsales\EshopCommunity\Internal\Domain\Authentication\Bridge\RandomTokenGeneratorBridgeInterface;
+use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface;
 
 /**
  * User manager.
@@ -1711,55 +1712,79 @@ protected function update()
     /**
      * Checks for already used email
      *
-     * @param string $sEmail user email/login
+     * @param string $email user email/login
      *
      * @return bool
      */
-    public function checkIfEmailExists($sEmail)
+    public function checkIfEmailExists($email)
     {
-        $myConfig = \OxidEsales\Eshop\Core\Registry::getConfig();
-        // We force reading from master to prevent issues with slow replications or open transactions (see ESDEV-3804).
-        $masterDb = \OxidEsales\Eshop\Core\DatabaseProvider::getMaster();
-        $iShopId = $myConfig->getShopId();
-        $blExists = false;
+        if (!$email) {
+            return false;
+        }
 
-        $sQ = 'select oxshopid, oxrights, oxpassword from oxuser where oxusername = :oxusername';
-        $params = [
-            ':oxusername' => (string) $sEmail
-        ];
-        if (($sOxid = $this->getId())) {
-            $sQ .= " and oxid <> :notoxid";
-            $params[':notoxid'] = $sOxid;
+        $config = Registry::getConfig();
+        $masterDb = DatabaseProvider::getMaster();
+        $shopId = $config->getShopId();
+
+        $query = 'SELECT oxshopid, oxrights, oxpassword FROM oxuser WHERE oxusername = :oxusername';
+        $params = [':oxusername' => (string) $email];
+
+        if ($id = $this->getId()) {
+            $query .= " AND oxid <> :notoxid";
+            $params[':notoxid'] = $id;
         }
-        $oRs = $masterDb->select($sQ, $params);
-        if ($oRs != false && $oRs->count() > 0) {
-            if ($this->_blMallUsers) {
-                $blExists = true;
-                if ($oRs->fields[1] == 'user' && !$oRs->fields[2]) {
-                    // password is not set - allow to override
-                    $blExists = false;
-                }
-            } else {
-                $blExists = false;
-                while (!$oRs->EOF) {
-                    if ($oRs->fields[1] != 'user') {
-                        // exists admin with same login - must not allow
-                        $blExists = true;
-                        break;
-                    } elseif ($oRs->fields[0] == $iShopId && $oRs->fields[2]) {
-                        // exists same login (with password) in same shop
-                        $blExists = true;
-                        break;
-                    }
 
-                    $oRs->fetchRow();
-                }
+        $result = $masterDb->select($query, $params);
+
+        if (!$result || $result->count() === 0) {
+            return false;
+        }
+
+        if ($this->_blMallUsers) {
+            if ($result->fields[1] === 'user' && !$result->fields[2]) {
+                return false; // No password set - allow override
+            }
+            return true;
+        }
+
+        while (!$result->EOF) {
+            if ($result->fields[1] !== 'user') {
+                return true; // Admin user exists
             }
+
+            if ($result->fields[0] == $shopId && ($result->fields[2])) {
+                return true; // User exists in same shop with password
+            }
+
+            $result->fetchRow();
         }
 
-        return $blExists;
+        return false;
     }
 
+    public function isEmailInUse(string $email): bool
+    {
+        $queryBuilder = ContainerFacade::get(QueryBuilderFactoryInterface::class)->create();
+        $queryBuilder
+            ->select('1')
+            ->from('oxuser')
+            ->where('oxusername = :email')
+            ->andWhere('oxshopid = :shopId')
+            ->setParameters([
+                'email' => $email,
+                'shopId' => Registry::getConfig()->getShopId()
+            ]);
+
+        if ($this->getId()) {
+            $queryBuilder
+                ->andWhere('oxid != :currentUserId')
+                ->setParameter('currentUserId', $this->getId());
+        }
+
+        return (bool) $queryBuilder->execute()->fetchOne();
+    }
+
+
     /**
      * Returns user recommendation list object
      *
diff --git a/source/Application/translations/de/lang.php b/source/Application/translations/de/lang.php
index 8bc57bb5e2..cbffc82dbb 100644
--- a/source/Application/translations/de/lang.php
+++ b/source/Application/translations/de/lang.php
@@ -163,7 +163,7 @@
 'ERROR_MESSAGE_USER_NOVALUES'                                 => 'E-Mail und Passwort müssen ausgefüllt sein!',
 'ERROR_MESSAGE_USER_USERCREATIONFAILED'                       => 'Fehler beim Anlegen des Benutzers!',
 'ERROR_MESSAGE_USER_UPDATE_FAILED'                            => 'Fehler beim Aktualisieren der Benutzerdaten!',
-'ERROR_MESSAGE_USER_USEREXISTS'                               => '%s konnte nicht registriert werden. Haben Sie bereits ein Kundenkonto bei uns?',
+'ERROR_MESSAGE_USER_USEREXISTS'                               => 'Bei dieser E-Mail-Adresse ist ein Fehler aufgetreten. Bitte wenden Sie sich an unseren Support.',
 'ERROR_MESSAGE_VERSION_EXPIRED1'                              => 'Ihre Version ist leider abgelaufen. Bitte kontaktieren Sie',
 'ERROR_MESSAGE_VOUCHER_INCORRECTPRICE'                        => 'Einkaufswert ist zu niedrig für diesen Gutschein!',
 'ERROR_MESSAGE_VOUCHER_ISRESERVED'                            => 'Gutschein ist reserviert!',
diff --git a/source/Application/translations/en/lang.php b/source/Application/translations/en/lang.php
index b2bf212c7e..355969e1a8 100644
--- a/source/Application/translations/en/lang.php
+++ b/source/Application/translations/en/lang.php
@@ -163,7 +163,7 @@
 'ERROR_MESSAGE_USER_NOVALUES'                                 => 'E-mail address and password have to be entered!',
 'ERROR_MESSAGE_USER_USERCREATIONFAILED'                       => 'Error creating the user!',
 'ERROR_MESSAGE_USER_UPDATE_FAILED'                            => 'Error while updating the user data!',
-'ERROR_MESSAGE_USER_USEREXISTS'                               => 'Not possible to register %s. Maybe you have already registered?',
+'ERROR_MESSAGE_USER_USEREXISTS'                               => 'An error has occurred with this e-mail address. Please contact our support.',
 'ERROR_MESSAGE_VERSION_EXPIRED1'                              => 'Your version is expired. Please contact',
 'ERROR_MESSAGE_VOUCHER_INCORRECTPRICE'                        => 'The total price is too low for this coupon!',
 'ERROR_MESSAGE_VOUCHER_ISRESERVED'                            => 'This coupon is reserved!',
diff --git a/source/Core/InputValidator.php b/source/Core/InputValidator.php
index 2de1e4f51d..ddd7bda956 100644
--- a/source/Core/InputValidator.php
+++ b/source/Core/InputValidator.php
@@ -10,7 +10,9 @@
 use OxidEsales\Eshop\Application\Model\Address;
 use OxidEsales\Eshop\Application\Model\User;
 use OxidEsales\Eshop\Core\Exception\ArticleInputException;
+use OxidEsales\Eshop\Core\Exception\InputException;
 use OxidEsales\Eshop\Core\Exception\StandardException;
+use OxidEsales\Eshop\Core\Exception\UserException;
 use OxidEsales\Eshop\Core\Registry;
 use OxidEsales\Eshop\Core\Str;
 use OxidEsales\EshopCommunity\Core\Di\ContainerFacade;
@@ -107,24 +109,28 @@ public function validateBasketAmount($amount)
      */
     public function checkLogin($user, $login, $invAddress)
     {
-        $login = (isset($invAddress['oxuser__oxusername'])) ? $invAddress['oxuser__oxusername'] : $login;
+        $login = (isset($invAddress['oxuser__oxusername']))
+            ? $invAddress['oxuser__oxusername']
+            : $login;
+
+        if (
+            isset($user->oxuser__oxpassword->value) &&
+            $user->oxuser__oxpassword->value &&
+            $login != $user->oxuser__oxusername->value
+        ) {
+            $newPassword = (isset($invAddress['oxuser__oxpassword']) && $invAddress['oxuser__oxpassword'])
+                ? $invAddress['oxuser__oxpassword']
+                : Registry::getRequest()->getRequestEscapedParameter('user_password');
 
-        // check only for users with password during registration
-        // if user wants to change user name - we must check if passwords are ok before changing
-        if (isset($user->oxuser__oxpassword->value) && $user->oxuser__oxpassword->value && $login != $user->oxuser__oxusername->value) {
-            // on this case password must be taken directly from request
-            $newPassword = (isset($invAddress['oxuser__oxpassword']) && $invAddress['oxuser__oxpassword']) ? $invAddress['oxuser__oxpassword'] : Registry::getRequest()->getRequestEscapedParameter('user_password');
             if (!$newPassword) {
-                // 1. user forgot to enter password
-                $exception = oxNew(\OxidEsales\Eshop\Core\Exception\InputException::class);
-                $exception->setMessage(\OxidEsales\Eshop\Core\Registry::getLang()->translateString('ERROR_MESSAGE_INPUT_NOTALLFIELDS'));
+                $message = Registry::getLang()->translateString('ERROR_MESSAGE_INPUT_NOTALLFIELDS');
+                $exception = oxNew(InputException::class, $message);
 
                 return $this->addValidationError("oxuser__oxpassword", $exception);
             } else {
-                // 2. entered wrong password
                 if (!$user->isSamePassword($newPassword)) {
-                    $exception = oxNew(\OxidEsales\Eshop\Core\Exception\UserException::class);
-                    $exception->setMessage(\OxidEsales\Eshop\Core\Registry::getLang()->translateString('ERROR_MESSAGE_PASSWORD_DO_NOT_MATCH'));
+                    $message = Registry::getLang()->translateString('ERROR_MESSAGE_PASSWORD_DO_NOT_MATCH');
+                    $exception = oxNew(UserException::class, $message);
 
                     return $this->addValidationError("oxuser__oxpassword", $exception);
                 }
@@ -132,9 +138,8 @@ public function checkLogin($user, $login, $invAddress)
         }
 
         if ($user->checkIfEmailExists($login)) {
-            //if exists then we do not allow to do that
-            $exception = oxNew(\OxidEsales\Eshop\Core\Exception\UserException::class);
-            $exception->setMessage(sprintf(\OxidEsales\Eshop\Core\Registry::getLang()->translateString('ERROR_MESSAGE_USER_USEREXISTS'), $login));
+            $message = Registry::getLang()->translateString('ERROR_MESSAGE_USER_USEREXISTS');
+            $exception = oxNew(UserException::class, $message);
 
             return $this->addValidationError("oxuser__oxusername", $exception);
         }
diff --git a/tests/Codeception/Acceptance/Admin/UserCest.php b/tests/Codeception/Acceptance/Admin/UserCest.php
index 8e99babc8a..e8023b7c97 100644
--- a/tests/Codeception/Acceptance/Admin/UserCest.php
+++ b/tests/Codeception/Acceptance/Admin/UserCest.php
@@ -14,6 +14,7 @@
 use OxidEsales\Codeception\Admin\DataObject\AdminUser;
 use OxidEsales\Codeception\Admin\DataObject\AdminUserAddresses;
 use OxidEsales\Codeception\Admin\DataObject\AdminUserExtendedInfo;
+use OxidEsales\Codeception\Module\Translation\Translator;
 use OxidEsales\EshopCommunity\Tests\Codeception\Support\AcceptanceTester;
 
 #[Group('admin')]
@@ -197,6 +198,39 @@ public function updatePassword(AcceptanceTester $I): void
             ->login($userData['userLoginName'], $newPass);
     }
 
+    public function testChangeUserEmail(AcceptanceTester $I): void
+    {
+        $I->wantToTest('changing user email addresses with validation in admin');
+
+        $userData = Fixtures::get('existingUser');
+        $guestUserData = Fixtures::get('existingGuestUser');
+        $adminUserData = Fixtures::get('adminUser');
+        $newEmail = 'example02@oxid-esales.dev';
+
+        $I->amGoingTo('login as admin and find the test user');
+        $adminUsersPage = $I->loginAdmin()
+            ->openUsers()
+            ->findByUserName($userData['userLoginName']);
+
+        $I->amGoingTo('try to change email to an existing guest user email');
+        $adminUsersPage->updateUsername($guestUserData['userLoginName']);
+        $I->expect('to see an error message about existing user');
+        $I->see(Translator::translate('EXCEPTION_USER_USEREXISTS'));
+
+        $I->amGoingTo('try to change email to an existing admin email');
+        $adminUsersPage->updateUsername($adminUserData['userLoginName']);
+        $I->expect('to see an error message about existing user');
+        $I->see(Translator::translate('EXCEPTION_USER_USEREXISTS'));
+
+        $I->amGoingTo('change user email to a new valid email address');
+        $adminUsersPage->updateUsername($newEmail);
+        $I->expect('not to see any error message');
+        $I->dontSee(Translator::translate('EXCEPTION_USER_USEREXISTS'));
+
+        $I->amGoingTo('change the email back to the original one');
+        $adminUsersPage->updateUsername($userData['userLoginName']);
+    }
+
     private function createAdminTestUser(
         AcceptanceTester $I,
         AdminUser $user,
diff --git a/tests/Codeception/Acceptance/UserAccountCest.php b/tests/Codeception/Acceptance/UserAccountCest.php
index e218fd48e5..8b2eb5528c 100644
--- a/tests/Codeception/Acceptance/UserAccountCest.php
+++ b/tests/Codeception/Acceptance/UserAccountCest.php
@@ -122,36 +122,60 @@ public function sendUserPasswordReminder(AcceptanceTester $I): void
     #[group('myAccount')]
     public function changeUserEmailInBillingAddress(AcceptanceTester $I): void
     {
-        $I->wantTo('change user email in my account');
+        $I->wantToTest('changing user email address in my account billing information');
 
         $userData = $this->getExistingUserData();
+        $guestUserData = $this->getExistingGuestUserData();
+        $adminUserData = $this->getAdminUserData();
+        $newEmail = 'example02@oxid-esales.dev';
 
+        $I->amGoingTo('login to shop and navigate to billing address form');
         $userAddressPage = $I->openShop()
             ->loginUser($userData['userLoginName'], $userData['userPassword'])
             ->openAccountPage()
             ->openUserAddressPage()
             ->openUserBillingAddressForm();
+
+        $I->expect('to see default country and state selections');
         $I->see('Germany', $userAddressPage->billCountryId);
         $I->see(Translator::translate('PLEASE_SELECT_STATE'), $userAddressPage->billStateId);
 
-        //change user password
-        $userAddressPage = $userAddressPage->changeEmail('example02@oxid-esales.dev', $userData['userPassword']);
+        $I->amGoingTo('try to change email to an existing guest user email');
+        $userAddressPage->changeEmail($guestUserData['userLoginName'], $userData['userPassword']);
+        $I->expect('to see an error message about existing user');
+        $I->see(Translator::translate('ERROR_MESSAGE_USER_USEREXISTS'));
+
+        $I->amGoingTo('try to change email to an existing admin email');
+        $userAddressPage->openUserBillingAddressForm()
+            ->changeEmail($adminUserData['userLoginName'], $userData['userPassword']);
+        $I->expect('to see an error message about existing user');
+        $I->see(Translator::translate('ERROR_MESSAGE_USER_USEREXISTS'));
 
+        $I->amGoingTo('change user email to a new valid email address');
+        $userAddressPage = $userAddressPage->openUserBillingAddressForm()
+            ->changeEmail($newEmail, $userData['userPassword']);
+        $I->expect('not to see any error messages');
+        $I->dontSee(Translator::translate('ERROR_MESSAGE_USER_USEREXISTS'));
         $I->dontSee(Translator::translate('COMPLETE_MARKED_FIELDS'));
-        $userAddressPage = $userAddressPage->logoutUser();
 
-        //try to login with old and new email address
+        $I->amGoingTo('logout and try to login with the old email address');
+        $userAddressPage = $userAddressPage->logoutUser();
         $userAddressPage->loginUser($userData['userLoginName'], $userData['userPassword']);
+        $I->expect('to see login form and error message');
         $I->see(Translator::translate('LOGIN'));
         $I->see(Translator::translate('ERROR_MESSAGE_USER_NOVALIDLOGIN'), $userAddressPage->badLoginError);
-        //login with new email address
-        $userAddressPage->loginUser('example02@oxid-esales.dev', $userData['userPassword']);
+
+        $I->amGoingTo('login with the new email address');
+        $userAddressPage->loginUser($newEmail, $userData['userPassword']);
+        $I->expect('to be logged in successfully');
         $I->dontSee(Translator::translate('LOGIN'));
 
-        //change password back to original
+        $I->amGoingTo('change the email back to the original one');
         $userAddressPage->openUserBillingAddressForm()
             ->changeEmail('example_test@oxid-esales.dev', $userData['userPassword'])
             ->logoutUser();
+        $I->expect('to be logged out');
+        $I->see(Translator::translate('LOGIN'));
     }
 
     #[group('myAccount')]
@@ -287,6 +311,16 @@ private function getExistingUserData()
         return Fixtures::get('existingUser');
     }
 
+    private function getExistingGuestUserData(): array
+    {
+        return Fixtures::get('existingGuestUser');
+    }
+
+    private function getAdminUserData(): array
+    {
+        return Fixtures::get('adminUser');
+    }
+
     private function getUserData(string $userId): array
     {
         return [
diff --git a/tests/Codeception/Support/Data/dump.sql b/tests/Codeception/Support/Data/dump.sql
index 8d486e0d11..ffc4b559c8 100644
--- a/tests/Codeception/Support/Data/dump.sql
+++ b/tests/Codeception/Support/Data/dump.sql
@@ -45,7 +45,8 @@ REPLACE INTO `oxobject2category` (`OXID`,                       `OXOBJECTID`, `O
 
 REPLACE INTO `oxuser` (`OXID`,     `OXACTIVE`, `OXRIGHTS`, `OXSHOPID`,   `OXUSERNAME`,         `OXPASSWORD`,                       `OXPASSSALT`,        `OXCUSTNR`, `OXUSTID`, `OXCOMPANY`,          `OXFNAME`,        `OXLNAME`,           `OXSTREET`,        `OXSTREETNR`, `OXADDINFO`,                   `OXCITY`,            `OXCOUNTRYID`,                `OXZIP`, `OXFON`,        `OXFAX`,       `OXSAL`, `OXBONI`, `OXCREATE`,            `OXREGISTER`,          `OXPRIVFON`,   `OXMOBFON`,    `OXBIRTHDATE`) VALUES
                       (      'testuser',          1,      'user',          1, 'example_test@oxid-esales.dev', 'c9dadd994241c9e5fa6469547009328a',                                                '7573657275736572',          8,         '', 'UserCompany šÄßüл',    'UserNamešÄßüл', 'UserSurnamešÄßüл', 'Musterstr.šÄßüл',          '1', 'User additional info šÄßüл', 'Musterstadt šÄßüл', 'testcountry_de', '79098', '0800 111111', '0800 111112',    'Mr',      500, '2008-02-05 14:42:42', '2008-02-05 14:42:42', '0800 111113', '0800 111114', '1980-01-01'),
-                      ('oxdefaultadmin',          1, 'malladmin',          1,        'admin@myoxideshop.com', '6cb4a34e1b66d3445108cd91b67f98b9','6631386565336161636139613634663766383538633566623662613036636539',          1,         '', 'Your Company Name',             'John',              'Doe',    'Maple Street',       '2425',                           '',          'Any City', 'testcountry_de',  '9041', '217-8918712', '217-8918713',    'MR',     1000, '2003-01-01 00:00:00', '2003-01-01 00:00:00',            '',            '', '0000-00-00');
+                      (      'testguest',          1,      'user',          1, 'example_guest@oxid-esales.dev', '',                                                '',          9,         '', 'UserCompany šÄßüл',    'UserNamešÄßüл', 'UserSurnamešÄßüл', 'Musterstr.šÄßüл',          '1', 'User additional info šÄßüл', 'Musterstadt šÄßüл', 'testcountry_de', '79098', '0800 111111', '0800 111112',    'Mr',      500, '2008-02-05 14:42:42', '2008-02-05 14:42:42', '0800 111113', '0800 111114', '1980-01-01'),
+                      ('oxdefaultadmin',          1, 'malladmin',          1,        'admin@myoxideshop.com', '6cb4a34e1b66d3445108cd91b67f98b9','6631386565336161636139613634663766383538633566623662613036636539',          1,         '', 'Your Company Name',             'John',              'Doe',    'Maple Street',       '2425',                           '',          'Any City', 'testcountry_de',  '9041', '217-8918712', '217-8918713',    'MR',     1000, '2003-01-01 00:00:00', '2003-01-01 00:00:00',            '',            '', '1970-01-01');
 
 #object2Group
 REPLACE INTO `oxobject2group` (`OXID`,                       `OXSHOPID`,   `OXOBJECTID`,   `OXGROUPSID`) VALUES
diff --git a/tests/Codeception/Support/Data/user.php b/tests/Codeception/Support/Data/user.php
index a090dfacc3..b26d226cb6 100644
--- a/tests/Codeception/Support/Data/user.php
+++ b/tests/Codeception/Support/Data/user.php
@@ -15,6 +15,13 @@
         'userName' => 'UserNamešÄßüл',
         'userLastName' => 'UserSurnamešÄßüл',
     ],
+    'existingGuestUser' => [
+        'userId' => 'testguest',
+        'userLoginName' => 'example_guest@oxid-esales.dev',
+        'userPassword' => '',
+        'userName' => 'UserNamešÄßüл',
+        'userLastName' => 'UserSurnamešÄßüл',
+    ],
     'adminUser' => [
         'userId' => 'admin',
         'userLoginName' => 'admin@myoxideshop.com',
diff --git a/tests/Integration/Application/Component/UserComponentTest.php b/tests/Integration/Application/Component/UserComponentTest.php
index 0cc5556d4c..c297a6b206 100644
--- a/tests/Integration/Application/Component/UserComponentTest.php
+++ b/tests/Integration/Application/Component/UserComponentTest.php
@@ -18,6 +18,8 @@
 final class UserComponentTest extends IntegrationTestCase
 {
     private string $userName = 'some-users-email@example.com';
+    private string $password = 'password123';
+
 
     public function setUp(): void
     {
@@ -156,6 +158,72 @@ public function testChangeUserWithExtraFormDataWillNotUpdateNonAddressUserFields
         $this->assertNotEquals($wrongUpdateExpiration, $userData['OXUPDATEEXP']);
     }
 
+    public function testChangeUserEmailValidation(): void
+    {
+        $existingUser = $this->createUser($this->userName);
+        $guestUser = $this->createUser('guest@example.com', true);
+        $secondUser = $this->createUser('second-user@example.com');
+
+        $this->assertEmailChangeRejected($secondUser['email'], $existingUser['email']);
+        $this->assertEmailChangeRejected($secondUser['email'], $guestUser['email']);
+        $this->assertEmailChangeAccepted($secondUser['email'], 'new-unique-email@example.com');
+    }
+
+    private function createUser(string $email, bool $isGuest = false): array
+    {
+        $userData = $this->getUserFormData();
+
+        if ($isGuest) {
+            unset($userData['lgn_pwd'], $userData['lgn_pwd2']);
+        }
+
+        $userData['oxuser__oxusername'] = $email;
+        $userData['lgn_usr'] = $email;
+        $_POST = $userData;
+
+        $this->getUserComponent()->createUser();
+
+        return [
+            'email' => $email
+        ];
+    }
+
+    private function assertEmailChangeRejected(string $currentEmail, string $newEmail): void
+    {
+        $this->userName = $currentEmail;
+
+        $requestData = $this->prepareChangeUserRequest($newEmail);
+        $_POST = $requestData;
+
+        $result = $this->getUserComponent()->changeuser_testvalues();
+
+        $this->assertNull($result);
+        $userData = $this->fetchUserData();
+        $this->assertEquals($currentEmail, $userData['OXUSERNAME']);
+    }
+
+    private function assertEmailChangeAccepted(string $currentEmail, string $newEmail): void
+    {
+        $this->userName = $currentEmail;
+
+        $requestData = $this->prepareChangeUserRequest($newEmail);
+        $_POST = $requestData;
+
+        $result = $this->getUserComponent()->changeuser_testvalues();
+
+        $this->assertEquals('account_user', $result);
+        $this->userName = $newEmail;
+        $userData = $this->fetchUserData();
+        $this->assertEquals($newEmail, $userData['OXUSERNAME']);
+    }
+
+    private function prepareChangeUserRequest(string $newEmail): array
+    {
+        $requestData = $this->getUserFormData();
+        $requestData['invadr']['oxuser__oxusername'] = $newEmail;
+        return $requestData;
+    }
+
     private function mockSession(): void
     {
         $sessionMock = $this->createPartialMock(Session::class, ['checkSessionChallenge']);
@@ -167,15 +235,14 @@ private function mockSession(): void
 
     private function getUserFormData(): array
     {
-        $password = uniqid('some-string-', true);
-
         return [
             'oxuser__oxfname' => uniqid('first-name-', true),
             'oxuser__oxlname' => uniqid('last-name-', true),
             'oxuser__oxusername' => $this->userName,
             'lgn_usr' => $this->userName,
-            'lgn_pwd' => $password,
-            'lgn_pwd2' => $password,
+            'lgn_pwd' => $this->password,
+            'lgn_pwd2' => $this->password,
+            'user_password' => $this->password,
             'invadr' => [
                 'oxuser__oxfname' => uniqid('first-name-', true),
                 'oxuser__oxlname' => uniqid('last-name-', true),
@@ -185,9 +252,19 @@ private function getUserFormData(): array
                 'oxuser__oxcity' => 'Freiburg',
                 'oxuser__oxcountryid' => 'a7c40f631fc920687.20179984',
             ],
+            'deladr' => [
+                'oxaddress__oxfname' => uniqid('del-first-name-', true),
+                'oxaddress__oxlname' => uniqid('del-last-name-', true),
+                'oxaddress__oxstreet' => uniqid('del-street-', true),
+                'oxaddress__oxstreetnr' => 123,
+                'oxaddress__oxzip' => 123,
+                'oxaddress__oxcity' => 'Freiburg',
+                'oxaddress__oxcountryid' => 'a7c40f631fc920687.20179984',
+            ]
         ];
     }
 
+
     private function getUserComponent(): UserComponent
     {
         $userComponent = oxNew(UserComponent::class);