From e269e46d8875346c73af7de15ae5eb8a9391076f Mon Sep 17 00:00:00 2001 From: Ernesto Herrera Date: Thu, 30 Jul 2026 10:49:23 -0600 Subject: [PATCH] =?UTF-8?q?fix(crm):=20env=C3=ADo=20de=20cotizaci=C3=B3n?= =?UTF-8?q?=20por=20correo=20con=20aiosmtplib.send=20(sin=20doble=20STARTT?= =?UTF-8?q?LS)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../api/v1/modules/crm/quotes/pdf_service.py | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/backend/api/v1/modules/crm/quotes/pdf_service.py b/backend/api/v1/modules/crm/quotes/pdf_service.py index 2225090..4fc9026 100644 --- a/backend/api/v1/modules/crm/quotes/pdf_service.py +++ b/backend/api/v1/modules/crm/quotes/pdf_service.py @@ -210,19 +210,25 @@ async def send_quote_email( part.add_header("Content-Disposition", f'attachment; filename="cotizacion-{ref}.pdf"') msg.attach(part) + if not (cfg.SMTP_USER and cfg.SMTP_PASSWORD): + raise HTTPException(status_code=503, detail="El correo saliente (SMTP) no está configurado en el servidor.") ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE try: - if cfg.SMTP_PORT == 465: - async with aiosmtplib.SMTP(hostname=cfg.SMTP_HOST, port=cfg.SMTP_PORT, use_tls=True, tls_context=ctx) as smtp: - await smtp.login(cfg.SMTP_USER, cfg.SMTP_PASSWORD) - await smtp.send_message(msg) - else: - async with aiosmtplib.SMTP(hostname=cfg.SMTP_HOST, port=cfg.SMTP_PORT, tls_context=ctx) as smtp: - await smtp.starttls(tls_context=ctx) - await smtp.login(cfg.SMTP_USER, cfg.SMTP_PASSWORD) - await smtp.send_message(msg) + # Puerto 465 = SSL implícito; los demás (587/2525/…) = STARTTLS. + await aiosmtplib.send( + msg, + hostname=cfg.SMTP_HOST, + port=cfg.SMTP_PORT, + username=cfg.SMTP_USER, + password=cfg.SMTP_PASSWORD, + use_tls=(cfg.SMTP_PORT == 465), + start_tls=(cfg.SMTP_PORT != 465), + tls_context=ctx, + validate_certs=False, + timeout=30, + ) except Exception as exc: logger.error("Error enviando cotización %s: %s", quote_id, exc) raise HTTPException(status_code=502, detail=f"No se pudo enviar el correo: {exc}")