Files
thrillwiki_django_no_react/backend/apps/email_service/backends.py
pacnpal d504d41de2 feat: complete monorepo structure with frontend and shared resources
- Add complete backend/ directory with full Django application
- Add frontend/ directory with Vite + TypeScript setup ready for Next.js
- Add comprehensive shared/ directory with:
  - Complete documentation and memory-bank archives
  - Media files and avatars (letters, park/ride images)
  - Deployment scripts and automation tools
  - Shared types and utilities
- Add architecture/ directory with migration guides
- Configure pnpm workspace for monorepo development
- Update .gitignore to exclude .django_tailwind_cli/ build artifacts
- Preserve all historical documentation in shared/docs/memory-bank/
- Set up proper structure for full-stack development with shared resources
2025-08-23 18:40:07 -04:00

103 lines
3.3 KiB
Python

from django.core.mail.backends.base import BaseEmailBackend
from django.core.mail.message import sanitize_address
from .services import EmailService
from .models import EmailConfiguration
class ForwardEmailBackend(BaseEmailBackend):
def __init__(self, fail_silently=False, **kwargs):
super().__init__(fail_silently=fail_silently)
self.site = kwargs.get("site", None)
def send_messages(self, email_messages):
"""
Send one or more EmailMessage objects and return the number of email
messages sent.
"""
if not email_messages:
return 0
num_sent = 0
for message in email_messages:
try:
sent = self._send(message)
if sent:
num_sent += 1
except Exception:
if not self.fail_silently:
raise
return num_sent
def _send(self, email_message):
"""Send an EmailMessage object."""
if not email_message.recipients():
return False
# Get the first recipient (ForwardEmail API sends to one recipient at a
# time)
to_email = email_message.to[0]
# Get site from connection or instance
if hasattr(email_message, "connection") and hasattr(
email_message.connection, "site"
):
site = email_message.connection.site
else:
site = self.site
if not site:
raise ValueError("Either request or site must be provided")
# Get the site's email configuration
try:
config = EmailConfiguration.objects.get(site=site)
except EmailConfiguration.DoesNotExist:
raise ValueError(
f"Email configuration not found for site: {
site.domain}"
)
# Get the from email, falling back to site's default if not provided
if email_message.from_email:
from_email = sanitize_address(
email_message.from_email, email_message.encoding
)
else:
from_email = config.default_from_email
# Extract clean email address
from_email = EmailService.extract_email(from_email)
# Get reply-to from message headers or use default
reply_to = None
if hasattr(email_message, "reply_to") and email_message.reply_to:
reply_to = email_message.reply_to[0]
elif (
hasattr(email_message, "extra_headers")
and "Reply-To" in email_message.extra_headers
):
reply_to = email_message.extra_headers["Reply-To"]
# Get message content
if email_message.content_subtype == "html":
# If it's HTML content, we'll send it as text for now
# You could extend this to support HTML emails if needed
text = email_message.body
else:
text = email_message.body
try:
EmailService.send_email(
to=to_email,
subject=email_message.subject,
text=text,
from_email=from_email,
reply_to=reply_to,
site=site,
)
return True
except Exception:
if not self.fail_silently:
raise
return False