124 lines
5.8 KiB
Python
124 lines
5.8 KiB
Python
"""
|
|
Custom email backend that uses SiteSettings for configuration.
|
|
"""
|
|
from django.core.mail.backends.smtp import EmailBackend as SMTPEmailBackend
|
|
from django.core.mail.backends.console import EmailBackend as ConsoleEmailBackend
|
|
from django.core.mail.backends.base import BaseEmailBackend
|
|
from django.conf import settings
|
|
from .models import SiteSettings
|
|
|
|
|
|
class SiteSettingsEmailBackend(BaseEmailBackend):
|
|
"""
|
|
Email backend that dynamically loads settings from SiteSettings model.
|
|
Falls back to Django settings if SiteSettings are not configured.
|
|
"""
|
|
|
|
def __init__(self, fail_silently=False, **kwargs):
|
|
super().__init__(fail_silently=fail_silently)
|
|
self._backend = None
|
|
self._backend_instance = None
|
|
self._load_backend()
|
|
|
|
def _load_backend(self):
|
|
"""Load the appropriate email backend based on SiteSettings."""
|
|
import logging
|
|
logger = logging.getLogger(__name__)
|
|
|
|
try:
|
|
site_settings = SiteSettings.get_settings()
|
|
backend_class = site_settings.email_backend
|
|
logger.info(f"Loading email backend: {backend_class}")
|
|
|
|
# If using SMTP, configure it with SiteSettings
|
|
if backend_class == 'django.core.mail.backends.smtp.EmailBackend':
|
|
# Get decrypted password
|
|
email_password = site_settings.get_email_password() if hasattr(site_settings, 'get_email_password') else site_settings.email_host_password
|
|
|
|
# Check if SMTP is properly configured
|
|
email_host = site_settings.email_host or getattr(settings, 'EMAIL_HOST', '')
|
|
|
|
# If no host is configured, fall back to console backend
|
|
if not email_host:
|
|
logger.warning("Email host not configured, using console backend")
|
|
self._backend = ConsoleEmailBackend(fail_silently=self.fail_silently)
|
|
else:
|
|
# Ensure TLS and SSL are mutually exclusive
|
|
use_tls = site_settings.email_use_tls
|
|
use_ssl = site_settings.email_use_ssl
|
|
|
|
# If both are True, prioritize TLS (common case)
|
|
if use_tls and use_ssl:
|
|
use_ssl = False
|
|
logger.warning("Both TLS and SSL were enabled. Disabling SSL and using TLS only.")
|
|
|
|
logger.info(f"Configuring SMTP: host={email_host}, port={site_settings.email_port}, user={site_settings.email_host_user}, tls={use_tls}, ssl={use_ssl}")
|
|
|
|
self._backend = SMTPEmailBackend(
|
|
host=email_host,
|
|
port=site_settings.email_port or getattr(settings, 'EMAIL_PORT', 587),
|
|
username=site_settings.email_host_user or getattr(settings, 'EMAIL_HOST_USER', ''),
|
|
password=email_password or getattr(settings, 'EMAIL_HOST_PASSWORD', ''),
|
|
use_tls=use_tls,
|
|
use_ssl=use_ssl,
|
|
timeout=site_settings.email_timeout or getattr(settings, 'EMAIL_TIMEOUT', 10),
|
|
fail_silently=self.fail_silently,
|
|
)
|
|
logger.info("SMTP backend configured successfully")
|
|
elif backend_class == 'django.core.mail.backends.console.EmailBackend':
|
|
logger.info("Using console email backend")
|
|
self._backend = ConsoleEmailBackend(fail_silently=self.fail_silently)
|
|
else:
|
|
# For other backends, try to import and instantiate
|
|
from django.utils.module_loading import import_string
|
|
backend_class_obj = import_string(backend_class)
|
|
self._backend = backend_class_obj(fail_silently=self.fail_silently)
|
|
logger.info(f"Loaded custom backend: {backend_class}")
|
|
except Exception as e:
|
|
# Fallback to console backend if there's an error
|
|
logger.exception(f"Error loading email backend from SiteSettings: {e}. Using console backend.")
|
|
self._backend = ConsoleEmailBackend(fail_silently=self.fail_silently)
|
|
|
|
def open(self):
|
|
"""Open a network connection."""
|
|
if self._backend:
|
|
return self._backend.open()
|
|
return False
|
|
|
|
def close(self):
|
|
"""Close the network connection."""
|
|
if self._backend:
|
|
return self._backend.close()
|
|
|
|
def send_messages(self, email_messages):
|
|
"""Send one or more EmailMessage objects and return the number sent."""
|
|
import logging
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# Reload backend before sending to get latest settings
|
|
# This ensures settings changes take effect immediately
|
|
self._load_backend()
|
|
if self._backend:
|
|
try:
|
|
# Log email details for debugging
|
|
for msg in email_messages:
|
|
logger.info(f"Sending email: To={msg.to}, Subject={msg.subject}, From={msg.from_email}")
|
|
|
|
result = self._backend.send_messages(email_messages)
|
|
logger.info(f"Successfully sent {result} email message(s)")
|
|
return result
|
|
except Exception as e:
|
|
error_msg = str(e)
|
|
logger.exception(f"Error sending email messages: {error_msg}")
|
|
|
|
# Log more details about the error
|
|
if hasattr(self._backend, 'host'):
|
|
logger.error(f"SMTP Host: {self._backend.host}, Port: {getattr(self._backend, 'port', 'N/A')}")
|
|
|
|
if not self.fail_silently:
|
|
raise
|
|
return 0
|
|
logger.warning("No email backend available, cannot send messages")
|
|
return 0
|
|
|