""" Email Reporter for POTE Sends formatted reports via SMTP email. """ import logging import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from pote.config import settings logger = logging.getLogger(__name__) class EmailReporter: """Sends email reports via SMTP.""" def __init__( self, smtp_host: str | None = None, smtp_port: int | None = None, smtp_user: str | None = None, smtp_password: str | None = None, from_email: str | None = None, ): """ Initialize email reporter. If parameters are not provided, will attempt to use settings from config. """ # Settings always defines these fields (with defaults), so direct access is safe. self.smtp_host: str = smtp_host or settings.smtp_host self.smtp_port: int = smtp_port or settings.smtp_port self.smtp_user: str = smtp_user or settings.smtp_user self.smtp_password: str = smtp_password or settings.smtp_password self.from_email: str = from_email or settings.from_email or "pote@localhost" def send_report( self, to_emails: list[str], subject: str, body_text: str, body_html: str | None = None, ) -> bool: """ Send an email report. Args: to_emails: List of recipient email addresses subject: Email subject line body_text: Plain text email body body_html: Optional HTML email body Returns: True if email sent successfully, False otherwise """ try: msg = MIMEMultipart("alternative") msg["Subject"] = subject msg["From"] = self.from_email msg["To"] = ", ".join(to_emails) # Attach plain text part msg.attach(MIMEText(body_text, "plain")) # Attach HTML part if provided if body_html: msg.attach(MIMEText(body_html, "html")) # Connect to SMTP server and send with smtplib.SMTP(self.smtp_host, self.smtp_port) as server: server.ehlo() if self.smtp_port == 587: # TLS server.starttls() server.ehlo() if self.smtp_user and self.smtp_password: server.login(self.smtp_user, self.smtp_password) server.send_message(msg) logger.info(f"Email sent successfully to {', '.join(to_emails)}") return True except Exception as e: logger.error(f"Failed to send email: {e}") return False def test_connection(self) -> bool: """ Test SMTP connection. Returns: True if connection successful, False otherwise """ try: with smtplib.SMTP(self.smtp_host, self.smtp_port, timeout=10) as server: server.ehlo() if self.smtp_port == 587: server.starttls() server.ehlo() if self.smtp_user and self.smtp_password: server.login(self.smtp_user, self.smtp_password) logger.info("SMTP connection test successful") return True except Exception as e: logger.error(f"SMTP connection test failed: {e}") return False