admin / Bid-Sentinel
publicBid Scrape and Tracking Application with AI Capability
Bid-Sentinel / bid-sentinel-v2 / backend / app / mailer.py
1519 B · main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | """Outgoing email (SMTP). Reports are sent only to the logged-in user's own address (enforced by the caller). Available only when SMTP_HOST is configured.""" from __future__ import annotations import logging from email.message import EmailMessage import aiosmtplib from app.config import settings logger = logging.getLogger("mailer") def is_available() -> bool: return bool(settings.smtp_host.strip()) async def send_report( to: str, subject: str, body: str, filename: str, content: bytes, content_type: str, ) -> None: """Send an email with a single file attachment. Raises on failure.""" msg = EmailMessage() msg["From"] = settings.smtp_from or settings.smtp_username or "bid-sentinel@localhost" msg["To"] = to msg["Subject"] = subject msg.set_content(body) maintype, _, subtype = content_type.partition("/") msg.add_attachment( content, maintype=maintype or "application", subtype=subtype or "octet-stream", filename=filename, ) kwargs: dict = {"hostname": settings.smtp_host, "port": settings.smtp_port} if settings.smtp_username: kwargs["username"] = settings.smtp_username kwargs["password"] = settings.smtp_password if settings.smtp_port == 465: kwargs["use_tls"] = True # implicit TLS else: kwargs["start_tls"] = settings.smtp_starttls # STARTTLS (e.g. port 587) await aiosmtplib.send(msg, **kwargs) logger.info("Emailed %r to %s", filename, to) |