101 lines
3.6 KiB
Python
Executable File
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()
|