update
This commit is contained in:
123
reports/email_backend.py
Normal file
123
reports/email_backend.py
Normal file
@@ -0,0 +1,123 @@
|
||||
"""
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user