import requests from django.conf import settings from django.contrib.sites.shortcuts import get_current_site from django.core.exceptions import ImproperlyConfigured from django.core.mail.message import sanitize_address from .models import EmailConfiguration import json import base64 class EmailService: @staticmethod def send_email( *, to: str, subject: str, text: str, from_email: str = None, html: str = None, reply_to: str = None, request=None, site=None, ): # Get the site configuration if site is None and request is not None: site = get_current_site(request) elif site is None: raise ImproperlyConfigured("Either request or site must be provided") try: # Fetch the email configuration for the current site email_config = EmailConfiguration.objects.get(site=site) api_key = email_config.api_key # Use provided from_email or construct from config if not from_email: from_email = f"{ email_config.from_name} <{ email_config.from_email}>" elif "<" not in from_email: # If from_email is provided but doesn't include a name, add the # configured name from_email = f"{email_config.from_name} <{from_email}>" # Use provided reply_to or fall back to config if not reply_to: reply_to = email_config.reply_to except EmailConfiguration.DoesNotExist: raise ImproperlyConfigured( f"Email configuration is missing for site: {site.domain}" ) # Ensure the reply_to address is clean reply_to = sanitize_address(reply_to, "utf-8") # Format data for the API data = { "from": from_email, # Now includes the name in format "Name " "to": to, "subject": subject, "text": text, "replyTo": reply_to, } # Add HTML version if provided if html: data["html"] = html # Debug output print("\nEmail Service Debug:") print(f"From: {from_email}") print(f"To: {to}") print(f"Reply-To: {reply_to}") print(f"API Key: {api_key}") print(f"Site: {site.domain}") print(f"Request URL: {settings.FORWARD_EMAIL_BASE_URL}/v1/emails") print(f"Request Data: {json.dumps(data, indent=2)}") # Create Basic auth header with API key as username and empty password auth_header = base64.b64encode(f"{api_key}:".encode()).decode() headers = { "Authorization": f"Basic {auth_header}", "Accept": "application/json", "Content-Type": "application/json", } try: response = requests.post( f"{settings.FORWARD_EMAIL_BASE_URL}/v1/emails", json=data, headers=headers, timeout=60, ) # Debug output print(f"Response Status: {response.status_code}") print(f"Response Headers: {dict(response.headers)}") print(f"Response Body: {response.text}") if response.status_code != 200: error_message = response.text if response.text else "Unknown error" raise Exception( f"Failed to send email (Status { response.status_code}): {error_message}" ) return response.json() except requests.RequestException as e: raise Exception(f"Failed to send email: {str(e)}") except Exception as e: raise Exception(f"Failed to send email: {str(e)}")