video-accessibility/backend/app/services/emailer.py
2025-08-24 16:28:33 -05:00

123 lines
4.3 KiB
Python

from jinja2 import Template
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Content, From, Mail, Subject, To
from ..core.config import settings
from ..core.logging import get_logger
logger = get_logger(__name__)
class EmailService:
def __init__(self):
if settings.sendgrid_api_key:
self.client = SendGridAPIClient(api_key=settings.sendgrid_api_key)
else:
logger.warning("SendGrid API key not configured")
self.client = None
async def send_completion_email(
self,
recipient_email: str,
job_title: str,
download_links: dict[str, dict[str, str]]
) -> bool:
"""Send job completion email with download links"""
if not self.client:
logger.error("SendGrid not configured, cannot send email")
return False
try:
# Render email template
html_content = self._render_completion_template(
job_title=job_title,
download_links=download_links
)
message = Mail(
from_email=From(settings.email_from, "Accessible Video Platform"),
to_emails=To(recipient_email),
subject=Subject(f"Your accessible video assets are ready: {job_title}"),
html_content=Content("text/html", html_content)
)
response = self.client.send(message)
if response.status_code == 202:
logger.info(f"Completion email sent successfully to {recipient_email}")
return True
else:
logger.error(f"Failed to send email, status code: {response.status_code}")
return False
except Exception as e:
logger.error(f"Email sending failed: {e}")
return False
def _render_completion_template(
self,
job_title: str,
download_links: dict[str, dict[str, str]]
) -> str:
"""Render the completion email HTML template"""
template_str = """
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Your Accessible Video Assets Are Ready</title>
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
.header { background-color: #4f46e5; color: white; padding: 20px; text-align: center; }
.content { padding: 20px; }
.download-section { margin: 20px 0; padding: 15px; background-color: #f9fafb; border-radius: 8px; }
.download-link { display: inline-block; padding: 10px 20px; margin: 5px; background-color: #4f46e5; color: white; text-decoration: none; border-radius: 5px; }
.footer { text-align: center; padding: 20px; color: #6b7280; font-size: 12px; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>Your Accessible Video Assets Are Ready!</h1>
</div>
<div class="content">
<h2>{{ job_title }}</h2>
<p>Great news! Your video accessibility assets have been processed and are ready for download.</p>
{% for language, files in download_links.items() %}
<div class="download-section">
<h3>{{ language.upper() }} Assets</h3>
{% for file_type, url in files.items() %}
<a href="{{ url }}" class="download-link">
Download {{ file_type|replace('_', ' ')|title }}
</a>
{% endfor %}
</div>
{% endfor %}
<p><strong>Important:</strong> These download links will expire in 24 hours for security purposes.</p>
<p>If you need assistance or have questions about your accessible video assets, please don't hesitate to contact our support team.</p>
</div>
<div class="footer">
<p>This email was sent by the Accessible Video Platform</p>
<p>Links expire in 24 hours for security</p>
</div>
</div>
</body>
</html>
"""
template = Template(template_str)
return template.render(
job_title=job_title,
download_links=download_links
)
# Global service instance
email_service = EmailService()