email_service.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. from config.settings import MAIL, MAIL_PASSWORD
  2. import smtplib
  3. from email.message import EmailMessage
  4. from logging import getLogger
  5. from contextlib import contextmanager
  6. from typing import Optional
  7. logger = getLogger(__name__)
  8. email_sender = None
  9. class EmailSender:
  10. def __init__(self, email: str, password: str):
  11. self.email = email
  12. self.password = password
  13. self._smtp: Optional[smtplib.SMTP_SSL] = None
  14. logger.debug(f"EmailSender initialized with {self.email}")
  15. @contextmanager
  16. def get_connection(self):
  17. if self._smtp is None:
  18. logger.info("Establishing new SMTP connection.")
  19. try:
  20. self._smtp = smtplib.SMTP_SSL('smtp.gmail.com', 465)
  21. self._smtp.login(self.email, self.password)
  22. logger.info("SMTP connection established and logged in.")
  23. except Exception as e:
  24. logger.error(f"Failed to establish SMTP connection: {e}")
  25. raise
  26. try:
  27. yield self._smtp
  28. except Exception as e:
  29. logger.error(f"Error during SMTP operation: {e}")
  30. self.close_connection()
  31. raise e
  32. def close_connection(self):
  33. if self._smtp:
  34. try:
  35. logger.info("Closing SMTP connection.")
  36. self._smtp.quit()
  37. logger.info("SMTP connection closed.")
  38. except Exception as e:
  39. logger.warning(f"Error closing SMTP connection: {e}")
  40. finally:
  41. self._smtp = None
  42. def send_email(self, subject: str, body: str, to: list[str], **kwargs):
  43. logger.debug(f"Preparing to send email to: {to} with subject: '{subject}' and kwargs: {kwargs}")
  44. msg = EmailMessage()
  45. msg['Subject'] = subject
  46. msg['From'] = self.email
  47. msg['To'] = ", ".join(to)
  48. msg.set_content('Este correo tiene contenido HTML.')
  49. msg.add_alternative(body.format(**kwargs), subtype='html')
  50. try:
  51. with self.get_connection() as smtp:
  52. smtp.send_message(msg)
  53. logger.info(f"Email sent to {to} with subject '{subject}'.")
  54. except Exception as e:
  55. logger.error(f"Failed to send email to {to}: {e}")
  56. raise
  57. def initialize_email_sender():
  58. global email_sender
  59. if email_sender is None:
  60. email_sender = EmailSender(MAIL, MAIL_PASSWORD)
  61. logger.info("EmailSender initialized globally.")
  62. return email_sender
  63. def send_email(subject: str, body: str, to: list[str], **kwargs):
  64. email_sender = initialize_email_sender()
  65. email_sender.send_email(subject, body, to, **kwargs)