import smtplib import logging from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from typing import Optional, List from app.core.config import settings logger = logging.getLogger(__name__) class EmailService: """ Email Service mirroring Spring Boot's JavaMailSender / EmailService. Supports SMTP (Gmail, SendGrid, AWS SES, etc.). If SMTP is not configured, logs the message to console (Dev Mode) so flows never crash. """ def __init__(self): self.host = getattr(settings, "SMTP_HOST", "") self.port = getattr(settings, "SMTP_PORT", 587) self.user = getattr(settings, "SMTP_USER", "") self.password = getattr(settings, "SMTP_PASSWORD", "") self.tls = getattr(settings, "SMTP_TLS", True) self.from_email = getattr(settings, "EMAILS_FROM_EMAIL", "noreply@authsec.com") def is_configured(self) -> bool: """Returns True if valid SMTP credentials are provided.""" return bool(self.host and self.user and self.password) def send_simple_message(self, to: str, subject: str, text: str, from_email: Optional[str] = None) -> bool: """Sends a plain text email (mirrors Spring Boot EmailService.sendSimpleMessage).""" sender = from_email or self.from_email if not self.is_configured(): print(f"\n==================== [DEV EMAIL SERVICE] ====================") print(f"To: {to}") print(f"From: {sender}") print(f"Subject: {subject}") print(f"Body:\n{text}") print(f"=============================================================\n") logger.info(f"[DEV EMAIL] Sent simulated email to {to}: {subject}") return True try: msg = MIMEMultipart() msg["From"] = sender msg["To"] = to msg["Subject"] = subject msg.attach(MIMEText(text, "plain")) with smtplib.SMTP(self.host, self.port) as server: if self.tls: server.starttls() server.login(self.user, self.password) server.send_message(msg) logger.info(f"Email successfully sent to {to}") return True except Exception as e: logger.error(f"Failed to send email to {to}: {e}") print(f"❌ Email sending error: {e}") return False def send_html_message(self, to: str, subject: str, html_content: str, from_email: Optional[str] = None) -> bool: """Sends an HTML formatted email.""" sender = from_email or self.from_email if not self.is_configured(): print(f"\n==================== [DEV EMAIL SERVICE (HTML)] ====================") print(f"To: {to}") print(f"Subject: {subject}") print(f"HTML Body:\n{html_content}") print(f"===================================================================\n") return True try: msg = MIMEMultipart("alternative") msg["From"] = sender msg["To"] = to msg["Subject"] = subject msg.attach(MIMEText(html_content, "html")) with smtplib.SMTP(self.host, self.port) as server: if self.tls: server.starttls() server.login(self.user, self.password) server.send_message(msg) return True except Exception as e: logger.error(f"Failed to send HTML email to {to}: {e}") return False def adduserviaadmin(self, to: str, subject: str, otp_or_url: str): """Mirrors Spring Boot EmailService.adduserviaadmin.""" body = f"Your verification code is: {otp_or_url}" return self.send_simple_message(to, subject, body) email_service = EmailService()