kaauh_ats/recruitment/services/email_service.py

119 lines
4.1 KiB
Python

from typing import List, Union
from django.core.mail import send_mail, EmailMessage
from django.contrib.auth import get_user_model
from django.template.loader import render_to_string
from django.conf import settings # To access EMAIL_HOST_USER, etc.
from recruitment.models import Message
UserModel = get_user_model()
User = UserModel # Type alias for clarity
class EmailService:
"""
A service class for sending single or bulk emails.
"""
def _send_email_internal(
self,
subject: str,
body: str,
recipient_list: List[str],
context:dict,
from_email: str = settings.DEFAULT_FROM_EMAIL,
html_content: Union[str, None] = None,
) -> int:
"""
Internal method to handle the actual sending using Django's email backend.
"""
try:
# Using EmailMessage for more control (e.g., HTML content)
from time import sleep
for recipient in recipient_list:
sleep(2)
email = EmailMessage(
subject=subject,
body=body,
from_email=from_email,
to=[recipient],
)
if html_content:
email.content_subtype = "html" # Main content is HTML
email.body = html_content # Overwrite body with HTML
# Returns the number of successfully sent emails (usually 1 or the count of recipients)
result=email.send(fail_silently=False)
recipient_user=User.objects.filter(email=recipient).first()
if result and recipient_user and not context["message_created"]:
Message.objects.create(sender=context['sender_user'],recipient=recipient_user,job=context['job'],subject=subject,content=context['email_message'],message_type='DIRECT',is_read=False)
return len(recipient_list)
except Exception as e:
# Log the error (in a real app, use Django's logger)
print(f"Error sending email to {recipient_list}: {e}")
return 0
# def send_single_email(
# self,
# user: User,
# subject: str,
# template_name: str,
# context: dict,
# from_email: str = settings.DEFAULT_FROM_EMAIL
# ) -> int:
# """
# Sends a single, template-based email to one user.
# """
# recipient_list = [user.email]
# # 1. Render content from template
# html_content = render_to_string(template_name, context)
# # You can optionally render a plain text version as well:
# # text_content = strip_tags(html_content)
# # 2. Call internal sender
# return self._send_email_internal(
# subject=subject,
# body="", # Can be empty if html_content is provided
# recipient_list=recipient_list,
# from_email=from_email,
# html_content=html_content
# )
def send_email_service(
self,
recipient_emails: List[str],
subject: str,
template_name: str,
context: dict,
from_email: str = settings.DEFAULT_FROM_EMAIL
) -> int:
"""
Sends the same template-based email to a list of email addresses.
Note: Django's EmailMessage can handle multiple recipients in one
transaction, which is often more efficient than sending them one-by-one.
"""
# 1. Render content from template (once)
html_content = render_to_string(template_name, context)
# 2. Call internal sender with all recipients
# The result here is usually 1 if successful, as it uses a single
# EmailMessage call for all recipients.
sent_count = self._send_email_internal(
subject=subject,
body="",
recipient_list=recipient_emails,
context=context,
from_email=from_email,
html_content=html_content,
)
print(f"Bulk email sent to {sent_count} recipients.")
# Return the count of recipients if successful, or 0 if failure
return len(recipient_emails) if sent_count > 0 else 0