Files
comercio-net/mail_sender.py
T

101 lines
3.6 KiB
Python
Executable File

"""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()