Cms: Can't catch email errors in user profile form anymore

Created on 30 Sep 2019  路  7Comments  路  Source: craftcms/cms

I'm pretty sure this used to work a few versions ago (circa 3.3.0).

Steps to reproduce

  1. Implement an advanced user profile form in Twig with email and password inputs as described here.
  2. Enter an invalid email address in the email input (e.g. lasjdfnasf) but the correct current password in the password input and submit the form.
  3. In the template, craft.app.session.getFlash('error') returns "Couldn鈥檛 save user.", but user.getFirstError('email') doesn't return anything. Also, user.email returns the current email address instead of the email address we entered. I also notice, by dumping user.getErrors(), that there is an unverifiedEmail error, which seems like it could help understand what is causing the issue:
array(1) { ["unverifiedEmail"]=> array(1) { [0]=> string(46) "Unverified Email is not a valid email address." } }

Additional info

  • Craft version: 3.3.6
  • PHP version: 7.3.8
  • Database driver & version: MySQL 5.7.26

Most helpful comment

@chasegiunta Actually, that鈥檚 a case for maybe this change not going far enough. I just went ahead and made it so unverifiedEmail is always included in user queries by default.

To get the fix early, change your craftcms/cms requirement in composer.json to:

"require": {
  "craftcms/cms": "dev-develop#613640d4cf86e6a83bfa6de7bcd28a44eb555bf0 as 3.3.8",
  "...": "..."
}

Then run composer update.

All 7 comments

This is expected behavior when email verification is enabled. However for the next release, Craft will go ahead and copy any unverifiedEmail attribute errors over to email, so they are where you鈥檇 expect.

Hey @brandonkelly, thank you, that fixes the error messages part, but user.email still returns the current email address instead of the email address the user entered.

Hm good point, but I don鈥檛 think it鈥檚 a good idea for us to change the actual email attribute value in this case. Instead I have updated the example form in the docs to output {{ formUser.unverifiedEmail ?? formUser.email }} 鈥撀爏o if unverifiedEmail is set, that will be output instead of email.

@brandonkelly Thank you, that makes sense. However, there is one more UX issue: when the user successfully submits the form (changing their email address) and the page reloads, the email input shows their old / current verified email address instead of their new (unverified) one. I understand that technically, the email they would use to log in is still the verified one until they verify the new one, but that may seem like what they just did didn't work. Maybe currentUser.unverifiedEmail should be set, and so it would just work with the same template code (formUser.unverifiedEmail ?? formUser.email)? And if we wanted to be more fancy we could do something like:

<input type="email" name="email" value="{{ formUser.unverifiedEmail ?? formUser.email }}">

{% if currentUser.unverifiedEmail %}

  (pending verification)

  <div>
    Verified Email: {{ currentUser.email }}
  </div>

{% endif %}

Yeah good point. That will be the case as of the next release.

@brandonkelly I recently sent in a support email that I believe was caused by not preloading this email value... You can go ahead and ignore that email now.

Looks like since you were bailing here in the verifyEmailForUser function, the user was never switched from pending status.

// Bail if they don't have an unverified email to begin with
        if (!$user->unverifiedEmail) {
            return true;
        }

If I go through my users table, and populate the unverifiedEmail column, this should clear it up I assume?

I have tons of people registering today, and who have over the past couple days - would appreciate a fast release, (or remind me on how to get this load this prerelease via composer please 馃槄 )

@chasegiunta Actually, that鈥檚 a case for maybe this change not going far enough. I just went ahead and made it so unverifiedEmail is always included in user queries by default.

To get the fix early, change your craftcms/cms requirement in composer.json to:

"require": {
  "craftcms/cms": "dev-develop#613640d4cf86e6a83bfa6de7bcd28a44eb555bf0 as 3.3.8",
  "...": "..."
}

Then run composer update.

Was this page helpful?
0 / 5 - 0 ratings