123 lines
4.3 KiB
Python
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()
|