95 lines
4.1 KiB
Python
95 lines
4.1 KiB
Python
"""Email service using Resend."""
|
|
import httpx
|
|
from typing import Optional, List
|
|
from app.core.config import settings
|
|
|
|
class EmailService:
|
|
RESEND_API = "https://api.resend.com/emails"
|
|
|
|
@classmethod
|
|
async def send(
|
|
cls,
|
|
to: List[str],
|
|
subject: str,
|
|
html: str,
|
|
text: Optional[str] = None
|
|
) -> bool:
|
|
if not settings.RESEND_API_KEY:
|
|
return False
|
|
|
|
async with httpx.AsyncClient() as client:
|
|
try:
|
|
response = await client.post(
|
|
cls.RESEND_API,
|
|
headers={
|
|
"Authorization": f"Bearer {settings.RESEND_API_KEY}",
|
|
"Content-Type": "application/json"
|
|
},
|
|
json={
|
|
"from": settings.EMAIL_FROM,
|
|
"to": to,
|
|
"subject": subject,
|
|
"html": html,
|
|
"text": text
|
|
}
|
|
)
|
|
return response.status_code == 200
|
|
except Exception:
|
|
return False
|
|
|
|
@classmethod
|
|
async def send_welcome(cls, email: str, name: str, org_name: str):
|
|
html = f"""
|
|
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
|
|
<h1 style="color: #4F46E5;">Welcome to JIRA AI Fixer! 🤖</h1>
|
|
<p>Hi {name},</p>
|
|
<p>You've been added to <strong>{org_name}</strong>.</p>
|
|
<p>JIRA AI Fixer automatically analyzes support issues and suggests code fixes using AI.</p>
|
|
<div style="margin: 30px 0;">
|
|
<a href="https://jira-fixer.startdata.com.br"
|
|
style="background: #4F46E5; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px;">
|
|
Get Started
|
|
</a>
|
|
</div>
|
|
<p style="color: #666;">— The JIRA AI Fixer Team</p>
|
|
</div>
|
|
"""
|
|
await cls.send([email], f"Welcome to {org_name} on JIRA AI Fixer", html)
|
|
|
|
@classmethod
|
|
async def send_analysis_complete(cls, email: str, issue_key: str, confidence: float, pr_url: Optional[str]):
|
|
html = f"""
|
|
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
|
|
<h1 style="color: #10B981;">Analysis Complete ✅</h1>
|
|
<p>Issue <strong>{issue_key}</strong> has been analyzed.</p>
|
|
<div style="background: #F3F4F6; padding: 20px; border-radius: 8px; margin: 20px 0;">
|
|
<p><strong>Confidence:</strong> {confidence:.0%}</p>
|
|
{f'<p><strong>Pull Request:</strong> <a href="{pr_url}">{pr_url}</a></p>' if pr_url else ''}
|
|
</div>
|
|
<a href="https://jira-fixer.startdata.com.br"
|
|
style="background: #4F46E5; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px;">
|
|
View Details
|
|
</a>
|
|
</div>
|
|
"""
|
|
await cls.send([email], f"Analysis Complete: {issue_key}", html)
|
|
|
|
@classmethod
|
|
async def send_weekly_digest(cls, email: str, org_name: str, stats: dict):
|
|
html = f"""
|
|
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
|
|
<h1 style="color: #4F46E5;">Weekly Digest 📊</h1>
|
|
<p>Here's what happened in <strong>{org_name}</strong> this week:</p>
|
|
<div style="background: #F3F4F6; padding: 20px; border-radius: 8px; margin: 20px 0;">
|
|
<p><strong>Issues Analyzed:</strong> {stats.get('analyzed', 0)}</p>
|
|
<p><strong>PRs Created:</strong> {stats.get('prs', 0)}</p>
|
|
<p><strong>Avg Confidence:</strong> {stats.get('confidence', 0):.0%}</p>
|
|
</div>
|
|
<a href="https://jira-fixer.startdata.com.br/reports"
|
|
style="background: #4F46E5; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px;">
|
|
View Full Report
|
|
</a>
|
|
</div>
|
|
"""
|
|
await cls.send([email], f"Weekly Digest: {org_name}", html)
|