4966fb4582e90c758a94961a9df521434b66d941
gperez2
  Fri Sep 18 15:08:08 2026 -0700
Updating hgLogin's CILogon-unverified-email wording (choose a username page, address-collision message, and new-account confirmation) for clarity and consistency, refs #38339

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

diff --git src/hg/hgLogin/hgLogin.c src/hg/hgLogin/hgLogin.c
index 3811c7338f9..723bed41d8a 100644
--- src/hg/hgLogin/hgLogin.c
+++ src/hg/hgLogin/hgLogin.c
@@ -421,33 +421,32 @@
  * have sent you a mail" paragraph can be printed above it.  Below the form it read as if a
  * confirmation had already gone to whatever was about to be typed into it.  The form is only
  * for an existing account whose address was never confirmed, and only for the person who just
  * came back from the provider -- pendingIdentityValid() is that check. */
 boolean offerNewAddress = fromProvider && isNotEmpty(existingUser) && pendingIdentityValid();
 char *encProvider = htmlEncode(provider);
 char *encAddress = htmlEncode(address);
 if (fromProvider)
     {
     if (isEmpty(existingUser))
         {
         /* An address the provider released and we would not take is not the same as no address
          * at all, and CILogon is the first case of it (#38339). */
         if (isNotEmpty(unverified))
             hPrintf("<p>You signed in with %s, and %s does not tell us whether the email "
-                "address it gave us really belongs to you, so we asked you for one. No %s "
-                "account uses <b>%s</b> yet, so we are making a new account for it. Confirming "
-                "the address is the last step.</p>",
+                "address it gave us belongs to you. A new %s account has been created because "
+                "no account uses <b>%s</b>.</p>",
                 encProvider, encProvider, brwName, encAddress);
         else
             hPrintf("<p>You signed in with %s, and %s did not tell us an email address, so we "
                 "asked you for one. No %s account uses <b>%s</b> yet, so we are making a new "
                 "account for it. Confirming the address is the last step.</p>",
                 encProvider, encProvider, brwName, encAddress);
         }
     else
         {
         char *encUser = htmlEncode(existingUser);
         /* Say that the address was changed.  Without this the page comes back looking exactly
          * as it did before the change, the new address being the only sign anything happened. */
         if (justChanged)
             hPrintf("<p>The email address on the %s account <b>%s</b> is now <b>%s</b>.</p>",
                 brwName, encUser, encAddress);
@@ -2522,34 +2521,34 @@
  * sign-in lands here, which surprised real users (#38341).  Keyed on whether an address arrived,
  * not on the provider's name: a mirror can call a provider anything it likes in hg.conf, so a
  * name test would silently miss it (#38213).
  * Test whether anything arrived, not whether oauthProviderEmail() accepted it.  A provider that
  * sends an address we cannot use -- spc_email_isvalid rejects every byte >= 127, so any
  * non-ASCII address -- also leaves us asking for one, but telling that user the provider shares
  * no address would be simply untrue.
  * Same for a provider that did release an address which we then dropped because it would not
  * say the address is verified: CILogon does exactly this, and "does not share your email
  * address with us" was plainly wrong for it (#38339). */
 char *unverified = oauthUnverifiedEmail();
 if (isEmpty(email) && unverified != NULL)
     {
     char *encUnverified = htmlEncode(unverified);
     hPrintf("<p>%s gave us the email address <b>%s</b>, but does not tell us whether that "
-        "address really belongs to you, so we cannot use it to sign you in to an account that "
-        "already has it. Enter an address below and confirm it once; after that this sign-in "
-        "will work on its own. If you already have an account, use another sign-in option "
-        "instead.</p>", label, encUnverified);
+        "address belongs to you. So we cannot use it to sign you in, even if an account "
+        "already has this address. Enter your email address below. Once it is confirmed, %s "
+        "will sign you in directly. If you already have an account, use another sign-in "
+        "option instead.</p>", label, encUnverified, label);
     freeMem(encUnverified);
     }
 else if (isEmpty(email))
     hPrintf("<p>A new %s account is created for any %s sign-in we have not seen before, because "
         "%s does not share your email address with us. So you cannot sign in to an existing "
         "account this way. Use another sign-in option if you do not want to create a new "
         "account.</p>", brwName, label, label);
 else if (providerEmail == NULL)
     hPrintf("<p>We cannot use the email address %s gave us, so please enter one below.</p>",
         label);
 printUsernameNote();
 hPrintf("<span style='color:red;'>%s</span>", errMsg ? errMsg : "");
 hPrintf("<form method=\"post\" action=\"%s\" name=\"completeAccountForm\">", hgLoginUrl);
 hPrintf("<div class=\"inputGroup\">"
     "<label for=\"userName\">Username</label>"
@@ -2674,42 +2673,40 @@
     char query[1024];
     char *addrMatch = sqlAddressMatch(email);
     sqlSafef(query, sizeof(query),
         "SELECT count(*) FROM gbMembers WHERE %-s AND accountActivated='Y'", addrMatch);
     freeMem(addrMatch);
     if (sqlQuickNum(conn, query) > 0)
         {
         char buf[1024];
         /* The provider may well have handed us this very address and we dropped it for want of
          * a verified flag (CILogon, #38339).  Saying it never gave us the address would be
          * wrong there, and the way out is a different one: what is missing is the provider's
          * word that the address is the user's, not the address itself. */
         char *unverified = oauthUnverifiedEmail();
         if ((unverified != NULL) && sameWord(unverified, email))
             safef(buf, sizeof(buf),
-                "An account with this email address already exists. %s gave us that address but "
-                "does not tell us that it is yours, so we cannot sign you in to that account. To "
-                "reach it, sign in with a provider that does confirm your email address, or with "
-                "your username and password. To create a new account instead, enter a different "
-                "email address.", oauthProviderLabel(provider));
+                "An account with this email address already exists. To sign in to that account, "
+                "use a sign-in option that verifies your email address, or use your username and "
+                "password. To create a new account instead, enter a different email address.");
         else
             safef(buf, sizeof(buf),
                 "An account with this email address already exists. %s did not give us that "
-                "address, so we cannot tell that it is yours and cannot sign you in to that "
-                "account. To reach it, sign in with a provider that does give us your email "
-                "address, or with your username and password. To create a new account instead, "
-                "enter a different email address.", oauthProviderLabel(provider));
+                "address, so we cannot tell that it belongs to you. To sign in to that account, "
+                "use a sign-in option that verifies your email address, or use your username and "
+                "password. To create a new account instead, enter a different email address.",
+                oauthProviderLabel(provider));
         freez(&errMsg);
         errMsg = cloneString(buf);
         completeAccountPage(conn);
         return;
         }
     }
 
 char *name = cartUsualString(cart, "oauth_pending_name", "");
 char *realName = isNotEmpty(name) ? name : user;
 
 /* The new account is created "activated" -- its address trusted for future auto-linking (see
  * resolveIdentity) -- when the address came from the provider.  An address the user typed gets
  * an inactive account and the usual confirmation mail, so a typed address can never be planted
  * as a trusted one.  An install that sends no mail has no way to confirm anything, so there it
  * is activated on the spot, the same compromise signup() makes. */