"""Envío de correo SMTP.""" import os import smtplib from email.message import EmailMessage from pathlib import Path from dotenv import load_dotenv # comercio-net/.env o .env en la raíz del repo # _BASE = Path(__file__).resolve().parent # load_dotenv(_BASE / ".env") # load_dotenv(_BASE.parent / ".env") # ============================================================================ load_dotenv(dotenv_path=".env") # ============================================================================ def _mail_config() -> dict: host = os.getenv("MAIL_HOST", "") port = int(os.getenv("MAIL_PORT", "587")) username = os.getenv("MAIL_USERNAME", "") # App passwords de Gmail suelen pegarse con espacios password = (os.getenv("MAIL_PASSWORD", "") or "").replace(" ", "") mail_from = os.getenv("MAIL_FROM", username) mail_to = os.getenv("MAIL_TO", "") if not all([host, username, password, mail_from, mail_to]): raise ValueError( "Faltan variables MAIL_* en .env " "(MAIL_HOST, MAIL_USERNAME, MAIL_PASSWORD, MAIL_FROM, MAIL_TO)" ) return { "host": host, "port": port, "username": username, "password": password, "mail_from": mail_from, "mail_to": mail_to, } # ============================================================================ def _smtp_send(msg: EmailMessage) -> None: cfg = _mail_config() with smtplib.SMTP(cfg["host"], cfg["port"], timeout=30) as smtp: smtp.ehlo() smtp.starttls() smtp.ehlo() smtp.login(cfg["username"], cfg["password"]) smtp.send_message(msg) # ============================================================================ def send_mail(subject: str | None = None, text: str | None = None) -> None: """Envía un correo de texto plano usando variables MAIL_* del .env.""" cfg = _mail_config() subject = subject if subject is not None else os.getenv("MAIL_SUBJECT", "Test Email") text = text if text is not None else os.getenv("MAIL_TEXT", "This is a test email") msg = EmailMessage() msg["Subject"] = subject msg["From"] = cfg["mail_from"] msg["To"] = cfg["mail_to"] msg.set_content(text) _smtp_send(msg) print(f"OK: correo enviado a {cfg['mail_to']} | subject={subject!r}") # ============================================================================ def send_validation_email(html_path: Path | str, subject: str | None = None) -> None: """Envía el HTML de validación a MAIL_TO (cuerpo HTML + adjunto).""" cfg = _mail_config() path = Path(html_path) if not path.is_file(): raise FileNotFoundError(f"No existe el HTML de validación: {path}") html = path.read_text(encoding="utf-8") if subject is None: subject = f"Validación OC — diferencias de precio/catálogo ({path.stem})" msg = EmailMessage() msg["Subject"] = subject msg["From"] = cfg["mail_from"] msg["To"] = cfg["mail_to"] msg.set_content( "Se detectaron diferencias de catálogo o precio en la OC. " "Ver el contenido HTML de este correo. " ) msg.add_alternative(html, subtype="html") #msg.add_attachment( # html.encode("utf-8"), # maintype="text", # subtype="html", # filename=path.name, #) _smtp_send(msg) print(f"OK: correo de validación enviado a {cfg['mail_to']} | subject={subject!r}") # ============================================================================ if __name__ == "__main__": send_mail()