Spaces:
Sleeping
Sleeping
feat: add confluence/slack search tools, chat history, cloud Qdrant support, sync trigger fixes
68af3c5 | """Fire-and-forget email sender using stdlib smtplib (no extra packages required).""" | |
| import smtplib | |
| import threading | |
| from email.mime.multipart import MIMEMultipart | |
| from email.mime.text import MIMEText | |
| from src.config import settings | |
| import logging | |
| logger = logging.getLogger(__name__) | |
| def send_email(to: str, subject: str, html: str) -> None: | |
| """Fire-and-forget β logs on failure, never raises.""" | |
| threading.Thread(target=lambda: send_email_sync(to, subject, html), daemon=True).start() | |
| def send_email_sync(to: str, subject: str, html: str) -> bool: | |
| """Synchronous send β returns True if sent, False if skipped or failed.""" | |
| if not settings.smtp_host or not settings.smtp_user: | |
| logger.warning("email_not_configured β skipping send to %s", to) | |
| return False | |
| try: | |
| msg = MIMEMultipart("alternative") | |
| msg["Subject"] = subject | |
| msg["From"] = settings.smtp_from | |
| msg["To"] = to | |
| msg.attach(MIMEText(html, "html")) | |
| with smtplib.SMTP(settings.smtp_host, settings.smtp_port) as s: | |
| s.starttls() | |
| s.login(settings.smtp_user, settings.smtp_password) | |
| s.sendmail(settings.smtp_from, to, msg.as_string()) | |
| logger.info("email_sent to=%s subject=%s", to, subject) | |
| return True | |
| except Exception: | |
| logger.exception("email_send_failed to=%s", to) | |
| return False | |