from config.settings import MAIL, MAIL_PASSWORD import smtplib from email.message import EmailMessage from logging import getLogger from contextlib import contextmanager from typing import Optional logger = getLogger(__name__) email_sender = None class EmailSender: def __init__(self, email: str, password: str): self.email = email self.password = password self._smtp: Optional[smtplib.SMTP_SSL] = None logger.debug(f"EmailSender initialized with {self.email}") @contextmanager def get_connection(self): if self._smtp is None: logger.info("Establishing new SMTP connection.") try: self._smtp = smtplib.SMTP_SSL('smtp.gmail.com', 465) self._smtp.login(self.email, self.password) logger.info("SMTP connection established and logged in.") except Exception as e: logger.error(f"Failed to establish SMTP connection: {e}") raise try: yield self._smtp except Exception as e: logger.error(f"Error during SMTP operation: {e}") self.close_connection() raise e def close_connection(self): if self._smtp: try: logger.info("Closing SMTP connection.") self._smtp.quit() logger.info("SMTP connection closed.") except Exception as e: logger.warning(f"Error closing SMTP connection: {e}") finally: self._smtp = None def send_email(self, subject: str, body: str, to: list[str], **kwargs): logger.debug(f"Preparing to send email to: {to} with subject: '{subject}' and kwargs: {kwargs}") msg = EmailMessage() msg['Subject'] = subject msg['From'] = self.email msg['To'] = ", ".join(to) msg.set_content('Este correo tiene contenido HTML.') msg.add_alternative(body.format(**kwargs), subtype='html') try: with self.get_connection() as smtp: smtp.send_message(msg) logger.info(f"Email sent to {to} with subject '{subject}'.") except Exception as e: logger.error(f"Failed to send email to {to}: {e}") raise def initialize_email_sender(): global email_sender if email_sender is None: email_sender = EmailSender(MAIL, MAIL_PASSWORD) logger.info("EmailSender initialized globally.") return email_sender def send_email(subject: str, body: str, to: list[str], **kwargs): email_sender = initialize_email_sender() email_sender.send_email(subject, body, to, **kwargs)