kaauh_ats/recruitment/services/email_service.py
2025-12-14 12:47:27 +03:00

107 lines
3.5 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.
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],
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)
email = EmailMessage(
subject=subject,
body=body,
from_email=from_email,
to=recipient_list,
)
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)
sent_count = email.send(fail_silently=False)
return sent_count
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_bulk_email(
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,
from_email=from_email,
html_content=html_content
)
# Return the count of recipients if successful, or 0 if failure
return len(recipient_emails) if sent_count > 0 else 0