Quitar la restricción de Gmail de toda la web

Se admite cualquier dominio de correo. Quedaba en dos validaciones (registro y
cambio de correo) y en tres textos:

- Register.email     «Correo electrónico de Gmail» -> «Correo electrónico»
- Register.emailRule «debe pertenecer a Gmail y con acceso al mismo» -> «debe ser
  válido y tener acceso al mismo» (el correo de activación sigue siendo real, así
  que se conserva el «con acceso»)
- ChangeEmail.info   se cae la frase «El nuevo correo debe ser de Gmail»

`GMAIL_RE` se queda sin uso y desaparece: ahora `EMAIL_RE` es la ÚNICA validación
de correo del sitio (registro, cambio, recuperación y login), así que no pueden
volver a divergir como pasaba (recuperar exigía Gmail y dejaba fuera a 16 de las
17 cuentas existentes).

Verificado: pasan inna@inna.cl, hotmail, outlook, proton, nightspire.gg y
dominios con doble punto; siguen fuera 15#1, textos sin @, dobles arrobas y
espacios. En la /es/create-account que sirve producción ya no aparece «Gmail».

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-15 19:20:42 +00:00
parent 4ee7d78994
commit 4a7a970206
5 changed files with 22 additions and 26 deletions
+12 -16
View File
@@ -158,23 +158,19 @@ export function gameAccountDisplayName(username: string): string {
}
/**
* Solo se admiten cuentas de Gmail. Lleva la `i` a propósito: sin ella
* `NOVAWOW86@GMAIL.COM` se rechazaba, y es justo como sale el correo en los
* mensajes que enviamos, así que quien lo copiara de ahí no podía ni registrarse
* ni recuperar la cuenta. El dominio del correo NO distingue mayúsculas.
*/
export const GMAIL_RE = /^[a-zA-Z0-9._%+-]+@gmail\.com$/i
/**
* Forma de correo, para distinguirlo de un nombre de usuario. Con Battle.net se
* entra con el correo, pero la gente prueba con la cuenta de juego («15#1»), que
* no tiene @.
* Forma de correo. La ÚNICA validación de correo del sitio: registro, cambio de
* correo, recuperación y login. Antes el registro/cambio/recuperación exigían
* Gmail; ya no, se admite cualquier dominio.
*
* A propósito NO exige punto en el dominio ni restringe a Gmail: el registro solo
* admite Gmail HOY, pero las cuentas ya creadas tienen correos de todo tipo
* (INNA@INNA.CL, e incluso Q@Q sin dominio), y validar de más al entrar las
* dejaría fuera. Solo hace falta separar «correo» de «usuario». Es el mismo
* criterio que aplica el navegador a un <input type="email">.
* Deliberadamente laxa. No exige punto en el dominio porque hay cuentas creadas
* con correos de todo tipo (INNA@INNA.CL, e incluso Q@Q) y validar de más al
* entrar o al recuperar las dejaría fuera. Lo único que hace falta es separar
* «correo» de «nombre de cuenta» («15#1», que no tiene @). Es el mismo criterio
* que aplica el navegador a un <input type="email">.
*
* Sin distinguir mayúsculas por definición (no hay letras literales): el dominio
* de un correo no las distingue, y los nuestros muestran la cuenta en MAYÚSCULAS,
* así que quien la copie de ahí y la pegue tiene que poder usarla.
*/
export const EMAIL_RE = /^[^\s@]+@[^\s@]+$/
+2 -2
View File
@@ -2,7 +2,7 @@ import crypto from 'node:crypto'
import type { RowDataPacket, ResultSetHeader } from 'mysql2'
import { db, DB } from './db'
import { authenticate } from './auth'
import { bnetMakeRegistration, normalizeEmail, GMAIL_RE } from './bnet'
import { bnetMakeRegistration, normalizeEmail, EMAIL_RE } from './bnet'
import { checkSecurityToken } from './security-token'
import { sendMail } from './mail'
import { confirmNewEmailHtml, confirmOldEmailHtml } from './emails'
@@ -26,7 +26,7 @@ export async function requestEmailChange(
const userId = session.accountId ?? 0
if (!curPassword || !curEmail || !newEmail || !confEmail || !token) return { success: false, error: 'missingFields' }
if (normalizeEmail(curEmail) !== current) return { success: false, error: 'wrongCurrentEmail' }
if (newEmail !== confEmail || !GMAIL_RE.test(newEmail)) return { success: false, error: 'invalidEmail' }
if (newEmail !== confEmail || !EMAIL_RE.test(newEmail)) return { success: false, error: 'invalidEmail' }
if (!(await checkSecurityToken(userId, token))) return { success: false, error: 'invalidToken' }
if (!(await authenticate(current, curPassword))) return { success: false, error: 'wrongCurrentPassword' }
+2 -2
View File
@@ -1,6 +1,6 @@
import type { ResultSetHeader, RowDataPacket } from 'mysql2'
import { db, DB } from './db'
import { normalizeEmail, bnetMakeRegistration, gameMakeRegistration, makeGameAccountUsername, GMAIL_RE } from './bnet'
import { normalizeEmail, bnetMakeRegistration, gameMakeRegistration, makeGameAccountUsername, EMAIL_RE } from './bnet'
import { sendMail } from './mail'
import { activationEmailHtml } from './emails'
import { randomToken } from './random-token'
@@ -31,7 +31,7 @@ export async function registerAccount(input: RegisterInput): Promise<Result> {
if (!password || !email) return { success: false, error: 'missingFields' }
if (password !== confPassword) return { success: false, error: 'passwordMismatch' }
if (password.length > 16) return { success: false, error: 'passwordTooLong' }
if (email !== confEmail || !GMAIL_RE.test(email)) return { success: false, error: 'invalidEmail' }
if (email !== confEmail || !EMAIL_RE.test(email)) return { success: false, error: 'invalidEmail' }
// ¿ya existe una cuenta Battle.net con ese email?
try {
+3 -3
View File
@@ -177,7 +177,7 @@
"alreadyLoggedCreate": "If you want to create an account, <logout>sign out</logout> first.",
"password": "Password",
"confPassword": "Confirm password",
"email": "Gmail email address",
"email": "Email address",
"confEmail": "Confirm email address",
"recruiter": "Recruiter (optional)",
"submit": "Create account",
@@ -194,7 +194,7 @@
"captchaFailed": "Anti-bot verification failed. Please retry.",
"bnetType": "Your account is a Battle.net account: it is identified by your email address.",
"passwordRule": "The password must be alphanumeric and up to 16 characters long.",
"emailRule": "The email must be a Gmail address you have access to.",
"emailRule": "The email must be valid and one you have access to.",
"activation1": "Once the account has been created successfully, an email with an activation link will be sent.",
"activation2": "If you do not use the activation link, the account cannot be used to connect to the server.",
"loginHint": "When logging in, use your EMAIL address.",
@@ -417,7 +417,7 @@
},
"ChangeEmail": {
"title": "Change email",
"info": "The current email must be entered exactly, respecting case. The new email must be a Gmail address. You need a security token.",
"info": "The current email must be entered exactly, respecting case. You need a security token.",
"currentPassword": "Current password",
"currentEmail": "Current email",
"newEmail": "New email",
+3 -3
View File
@@ -177,7 +177,7 @@
"alreadyLoggedCreate": "Si quieres crear una cuenta, primero <logout>desconecta</logout>.",
"password": "Contraseña",
"confPassword": "Confirmar contraseña",
"email": "Correo electrónico de Gmail",
"email": "Correo electrónico",
"confEmail": "Confirmar correo electrónico",
"recruiter": "Reclutante (opcional)",
"submit": "Crear cuenta",
@@ -194,7 +194,7 @@
"captchaFailed": "Verificación anti-bots fallida. Reintenta.",
"bnetType": "Tu cuenta es de tipo Battle.net: se identifica con tu correo electrónico.",
"passwordRule": "La contraseña debe ser alfanumérica y con una longitud de hasta 16 caracteres.",
"emailRule": "El correo debe pertenecer a Gmail y con acceso al mismo.",
"emailRule": "El correo debe ser válido y tener acceso al mismo.",
"activation1": "Una vez que la cuenta se haya creado exitosamente, se enviará un correo con un enlace de activación.",
"activation2": "De no usar el enlace de activación, la cuenta no podrá usarse para conectar al servidor.",
"loginHint": "Al iniciar sesión, ingresa con tu CORREO electrónico.",
@@ -417,7 +417,7 @@
},
"ChangeEmail": {
"title": "Cambiar correo",
"info": "El correo actual debe escribirse tal cual, respetando mayúsculas/minúsculas. El nuevo correo debe ser de Gmail. Necesitas un token de seguridad.",
"info": "El correo actual debe escribirse tal cual, respetando mayúsculas/minúsculas. Necesitas un token de seguridad.",
"currentPassword": "Contraseña actual",
"currentEmail": "Correo actual",
"newEmail": "Nuevo correo",