Correos: portar el diseño del tema y unificarlos en lib/emails.ts
Los correos usaban un shell inline distinto en cada remitente. Ahora salen todos de una sola maqueta, la de security_token, portada de las plantillas de Django. De las 7 de Django solo security_token y activation traían el diseño; las otras 5 eran HTML soso. Las plantillas de Django eran un volcado del DOM de Gmail. Al portarlas se quitó lo que no era diseño: los enlaces iban envueltos en el rastreador de Mailjet (079xk.mjt.lu), que además redirigía a ultimowow.com en vez de a nosotros; había un píxel de apertura, un "Click on me" oculto y atributos que mete Gmail al mostrar el correo. Las imágenes apuntaban al proxy de Gmail (ci3.googleusercontent.com), no a nuestro /static/, así que el diseño se rompía el día que Google dejara de servirlas. Ninguna URL va a fuego: todas cuelgan de SITE_URL, así que cambiar de dominio es tocar el .env. En un correo han de ser absolutas (se abre desde Gmail), así que se construyen a partir de esa variable. El logo nw-mail-logo.png daba 404: solo existía el .webp del tema, que es el de UltimoWoW (león negro + letras "UW"). El auténtico de NovaWoW, un león de acero sin letras, sobrevivía únicamente en la caché de Gmail y se recuperó de ahí (600x320 RGBA, íntegro). Verificado renderizando el original y el nuestro en un navegador y comparando: cuadran pixel a pixel. Eso destapó dos fallos que se corrigen aquí: faltaba la etiqueta <h1> de apertura, y el estilo de los párrafos de datos era el de la letra pequeña del pie (11px/17px) en vez del real (14px/21px). El activation de Django mandaba la contraseña en texto plano; aquí no se manda. mail.ts: leía EMAIL_USE_SSL pero ignoraba EMAIL_USE_TLS, así que en el puerto 587 el STARTTLS era oportunista y, si el servidor no lo ofrecía, nodemailer enviaba en claro. Ahora requireTLS lo hace obligatorio. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import { authenticate } from './auth'
|
||||
import { bnetMakeRegistration, normalizeEmail } from './bnet'
|
||||
import { checkSecurityToken } from './security-token'
|
||||
import { sendMail } from './mail'
|
||||
import { confirmNewEmailHtml, confirmOldEmailHtml } from './emails'
|
||||
import type { SessionData } from './session'
|
||||
|
||||
const GMAIL_RE = /^[a-zA-Z0-9._%+-]+@gmail\.com$/
|
||||
@@ -14,12 +15,6 @@ export interface Result {
|
||||
error?: string
|
||||
}
|
||||
|
||||
function shell(title: string, body: string): string {
|
||||
return `<!DOCTYPE html><html lang="es"><body style="font-family:Arial,sans-serif;background:#1b120b;color:#e8dccb;padding:24px">
|
||||
<div style="max-width:600px;margin:0 auto;background:#241812;border:1px solid #4a3320;border-radius:8px;padding:28px">
|
||||
<h1 style="color:#d79602">Nova WoW</h1><h2>${title}</h2>${body}</div></body></html>`
|
||||
}
|
||||
|
||||
export async function requestEmailChange(
|
||||
session: SessionData,
|
||||
curPassword: string,
|
||||
@@ -49,14 +44,14 @@ export async function requestEmailChange(
|
||||
await sendMail(
|
||||
current,
|
||||
`Confirma el cambio de correo - Nova WoW`,
|
||||
shell('Confirma el cambio de correo', `<p>Has solicitado cambiar tu correo a <strong>${newEmail}</strong>. Confirma desde tu correo actual:</p><p><a href="${link}" style="color:#d79602">Confirmar</a></p><p style="font-size:13px">${link}</p>`),
|
||||
confirmOldEmailHtml(session.username ?? current, newEmail, link),
|
||||
)
|
||||
return { success: true }
|
||||
}
|
||||
|
||||
export async function confirmOldEmail(hash: string): Promise<Result> {
|
||||
const [rows] = await db(DB.default).query<RowDataPacket[]>(
|
||||
'SELECT id, email, hash FROM home_accountactivation WHERE old_email_hash = ? AND is_used = 0',
|
||||
'SELECT id, email, hash, username FROM home_accountactivation WHERE old_email_hash = ? AND is_used = 0',
|
||||
[hash],
|
||||
)
|
||||
const act = rows[0]
|
||||
@@ -68,7 +63,7 @@ export async function confirmOldEmail(hash: string): Promise<Result> {
|
||||
await sendMail(
|
||||
act.email,
|
||||
`Confirma tu nuevo correo - Nova WoW`,
|
||||
shell('Confirma tu nuevo correo', `<p>Confirma este correo como el nuevo de tu cuenta:</p><p><a href="${link}" style="color:#d79602">Confirmar nuevo correo</a></p><p style="font-size:13px">${link}</p>`),
|
||||
confirmNewEmailHtml(act.username ?? act.email, link),
|
||||
)
|
||||
return { success: true }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user