""" Email SMTP sender (worker) – invio notifiche via aiosmtplib. Copia del sender backend: i due container sono separati. """ from datetime import datetime from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText import aiosmtplib DEFAULT_TIMEOUT = 15.0 class EmailSMTPError(Exception): def __init__(self, message: str, smtp_code: int | None = None): super().__init__(message) self.smtp_code = smtp_code async def send_email_notification( smtp_host: str, smtp_port: int, smtp_user: str, smtp_password: str, from_email: str, to_email: str, subject: str, body_text: str, body_html: str | None = None, from_name: str = "PEChub Notifiche", use_tls: bool = True, use_starttls: bool = False, timeout: float = DEFAULT_TIMEOUT, ) -> None: """ Invia un'email di notifica via SMTP. Raises: EmailSMTPError: in caso di errori di autenticazione, connessione o invio """ msg = MIMEMultipart("alternative") msg["Subject"] = subject msg["From"] = f"{from_name} <{from_email}>" if from_name else from_email msg["To"] = to_email msg["Date"] = datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S +0000") msg["X-Mailer"] = "PEChub/1.0" msg.attach(MIMEText(body_text, "plain", "utf-8")) if body_html: msg.attach(MIMEText(body_html, "html", "utf-8")) try: await aiosmtplib.send( msg, hostname=smtp_host, port=smtp_port, username=smtp_user, password=smtp_password, use_tls=use_tls, start_tls=use_starttls, timeout=timeout, ) except aiosmtplib.SMTPAuthenticationError as exc: raise EmailSMTPError( f"Autenticazione SMTP fallita: {exc}", smtp_code=535 ) from exc except aiosmtplib.SMTPConnectError as exc: raise EmailSMTPError( f"Connessione SMTP fallita a {smtp_host}:{smtp_port}: {exc}" ) from exc except aiosmtplib.SMTPException as exc: raise EmailSMTPError(f"Errore SMTP: {exc}") from exc except Exception as exc: raise EmailSMTPError(f"Errore invio email: {exc}") from exc