diff --git a/backend/api/services/email_service.py b/backend/api/services/email_service.py
index c2e9411..8976813 100644
--- a/backend/api/services/email_service.py
+++ b/backend/api/services/email_service.py
@@ -1,13 +1,147 @@
+import html
import os
import smtplib
import ssl
+from datetime import datetime
from email.message import EmailMessage
+from api.utils.email_verification import EMAIL_VERIFICATION_CODE_TTL_MINUTES
+
def _env_bool(name: str, default: str = "false") -> bool:
return os.getenv(name, default).strip().lower() in {"1", "true", "yes", "on"}
+def _build_verification_plain(username: str, code: str) -> str:
+ ttl = EMAIL_VERIFICATION_CODE_TTL_MINUTES
+ return "\n".join(
+ [
+ f"Hola {username},",
+ "",
+ "Tu código de verificación para Deck of Cards es:",
+ "",
+ code,
+ "",
+ f"Este código caduca en {ttl} minutos.",
+ "Si no has creado esta cuenta, puedes ignorar este correo.",
+ "",
+ "— Deck of Cards",
+ "Plataforma web para la elicitación de escalas de valor (DoC-MF).",
+ ]
+ )
+
+
+def _build_verification_html(username: str, code: str) -> str:
+ safe_username = html.escape(username)
+ frontend_url = os.getenv("FRONTEND_URL", "http://localhost:5173").rstrip("/")
+ logo_url = f"{frontend_url}/favicon.svg"
+ ttl = EMAIL_VERIFICATION_CODE_TTL_MINUTES
+ year = datetime.utcnow().year
+
+ return f"""
+
+
+
+
+ Verificación — Deck of Cards
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+ Deck of Cards
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+ |
+
+ Verificación de cuenta
+
+
+ Hola, {safe_username}
+
+
+ Gracias por registrarte. Introduce el siguiente código en la pantalla de registro para confirmar tu correo electrónico.
+
+
+
+
+ |
+
+ Tu código
+
+
+ {code}
+
+ |
+
+
+
+
+ El código caduca en {ttl} minutos.
+
+
+ Si no has creado esta cuenta, ignora este mensaje. Nadie más podrá usar tu correo sin el código.
+
+ |
+
+
+
+
+
+
+ |
+
+ Deck of Cards
+
+ Software Científico
+
+
+
+ Plataforma web para la elicitación de escalas de valor y construcción de conjuntos difusos interpretables (DoC-MF).
+
+
+ © {year} Deck of Cards App.
+
+
+ Basado en la metodología DoC-MF (D. García-Zamora, B. Dutta, J.R. Figueira y L. Martínez, EJOR, 2024).
+
+ |
+
+
+ |
+
+
+
+ |
+
+
+
+"""
+
+
def send_verification_email(recipient_email: str, username: str, code: str) -> bool:
smtp_host = os.getenv("SMTP_HOST")
if not smtp_host:
@@ -29,23 +163,11 @@ def send_verification_email(recipient_email: str, username: str, code: str) -> b
raise RuntimeError("SMTP_FROM_EMAIL o SMTP_USERNAME debe estar configurado")
message = EmailMessage()
- message["Subject"] = "Código de verificación de Deck of Cards"
+ message["Subject"] = "Código de verificación — Deck of Cards"
message["From"] = f"{smtp_from_name} <{smtp_from_email}>"
message["To"] = recipient_email
- message.set_content(
- "\n".join(
- [
- f"Hola {username},",
- "",
- "Tu código de verificación para Deck of Cards es:",
- "",
- code,
- "",
- "Este código caduca en unos minutos. Si no has creado esta cuenta,",
- "puedes ignorar este correo.",
- ]
- )
- )
+ message.set_content(_build_verification_plain(username, code))
+ message.add_alternative(_build_verification_html(username, code), subtype="html")
context = ssl.create_default_context()