Medisync / utils /email_utils.py
anique-1's picture
Deploy MediSync AI Backend with APK to Hugging Face
903c699
Raw
History Blame Contribute Delete
28.4 kB
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage # Added for embedding images
from dotenv import load_dotenv
import asyncio
from utils.url_utils import get_frontend_url
from utils.config_loader import get_setting
load_dotenv()
# GMAIL_USER and GMAIL_PASS are now fetched dynamically inside functions
# --- Base Email Template with Beautiful Design ---
EMAIL_BASE_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {{
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}}
.email-wrapper {{
max-width: 600px;
margin: 40px auto;
background: #ffffff;
border-radius: 20px;
overflow: hidden;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}}
.email-header {{
background: linear-gradient(135deg, #06b6d4 0%, #3b82f6 100%);
padding: 40px 30px;
text-align: center;
position: relative;
overflow: hidden;
}}
.email-header::before {{
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
animation: pulse 4s ease-in-out infinite;
}}
@keyframes pulse {{
0%, 100% {{ transform: scale(1); opacity: 0.5; }}
50% {{ transform: scale(1.1); opacity: 0.8; }}
}}
.logo {{
width: 120px; /* Increased size */
height: 120px; /* Increased size */
/* Removed background and box-shadow as image will provide styling */
border-radius: 15px;
display: inline-flex;
align-items: center;
justify-content: center;
margin-bottom: 15px;
position: relative;
z-index: 1;
}}
.logo img {{
width: 100%;
height: 100%;
object-fit: contain;
border-radius: 15px;
}}
.brand-name {{
color: white;
font-size: 28px;
font-weight: bold;
margin: 0;
position: relative;
z-index: 1;
}}
.email-body {{
padding: 40px 30px;
color: #333333;
line-height: 1.8;
}}
.greeting {{
font-size: 24px;
font-weight: bold;
color: #1e293b;
margin-bottom: 20px;
}}
.content {{
font-size: 16px;
color: #475569;
margin-bottom: 25px;
}}
.highlight {{
color: #06b6d4;
font-weight: 600;
}}
.button-container {{
text-align: center;
margin: 35px 0;
}}
.button {{
display: inline-block;
padding: 16px 40px;
background: linear-gradient(135deg, #06b6d4 0%, #3b82f6 100%);
color: white;
text-decoration: none;
border-radius: 12px;
font-weight: 600;
font-size: 16px;
box-shadow: 0 10px 30px rgba(6, 182, 212, 0.4);
transition: transform 0.3s ease;
}}
.info-box {{
background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
border-left: 4px solid #06b6d4;
padding: 20px;
border-radius: 12px;
margin: 25px 0;
}}
.info-box-title {{
font-weight: 600;
color: #0c4a6e;
margin-bottom: 10px;
font-size: 18px;
}}
.info-item {{
margin: 8px 0;
color: #475569;
}}
.alert-box {{
background: linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%);
border-left: 4px solid #ef4444;
padding: 20px;
border-radius: 12px;
margin: 25px 0;
}}
.alert-box-title {{
font-weight: 600;
color: #991b1b;
margin-bottom: 10px;
font-size: 18px;
}}
.success-box {{
background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
border-left: 4px solid #22c55e;
padding: 20px;
border-radius: 12px;
margin: 25px 0;
}}
.success-box-title {{
font-weight: 600;
color: #166534;
margin-bottom: 10px;
font-size: 18px;
}}
.footer {{
background: #f8fafc;
padding: 30px;
text-align: center;
border-top: 1px solid #e2e8f0;
}}
.footer-text {{
color: #64748b;
font-size: 14px;
margin: 5px 0;
}}
.social-links {{
margin: 20px 0;
}}
.social-link {{
display: inline-block;
width: 40px;
height: 40px;
background: linear-gradient(135deg, #06b6d4 0%, #3b82f6 100%);
border-radius: 50%;
margin: 0 5px;
line-height: 40px;
color: white;
text-decoration: none;
font-weight: bold;
}}
@media only screen and (max-width: 600px) {{
.email-wrapper {{
margin: 20px;
}}
.email-body {{
padding: 30px 20px;
}}
}}
</style>
</head>
<body>
<div class="email-wrapper">
<div class="email-header">
<div class="logo">
<img src="cid:mediflow-logo" alt="MediSync Logo" style="width: 100%; height: 100%; object-fit: contain; border-radius: 15px;">
</div>
<h1 class="brand-name">MediSync</h1>
</div>
<div class="email-body">
{content}
</div>
<div class="footer">
<div class="social-links">
<a href="#" class="social-link">f</a>
<a href="#" class="social-link">t</a>
<a href="#" class="social-link">in</a>
</div>
<p class="footer-text">Β© 2025 MediSync. All rights reserved.</p>
<p class="footer-text">AI-Powered Medicine Dispenser System</p>
<p class="footer-text" style="margin-top: 15px;">
<a href="#" style="color: #06b6d4; text-decoration: none;">Privacy Policy</a> |
<a href="#" style="color: #06b6d4; text-decoration: none;">Terms of Service</a>
</p>
</div>
</div>
</body>
</html>
"""
# --- Account Verification Email ---
ACCOUNT_VERIFICATION_EMAIL_SUBJECT = "Verify your account - MediSync"
ACCOUNT_VERIFICATION_EMAIL_CONTENT = """
<p class="greeting">Welcome, {full_name}! πŸŽ‰</p>
<p class="content">
Thank you for registering with <span class="highlight">MediSync</span>, your AI-Powered Medicine Dispenser System.
</p>
<p class="content">
To get started and access all the amazing features, please verify your email address by clicking the button below:
</p>
<div class="button-container">
<a href="{verification_link}" class="button" style="color: #ffffff; text-decoration: none; display: inline-block; padding: 16px 40px; background: linear-gradient(135deg, #06b6d4 0%, #3b82f6 100%); border-radius: 12px; font-weight: 600; font-size: 16px; box-shadow: 0 10px 30px rgba(6, 182, 212, 0.4); transition: transform 0.3s ease;">βœ“ Verify Email Address</a>
</div>
<p class="content" style="font-size: 14px; color: #64748b; margin-top: 20px;">
If the button doesn't work, copy and paste this link into your browser:
</p>
<p class="content" style="word-break: break-all; background: #f8fafc; padding: 15px; border-radius: 8px; border: 1px solid #e2e8f0; font-family: 'Courier New', monospace; font-size: 14px; color: #06b6d4;">
{verification_link}
</p>
<p class="content" style="font-size: 14px; color: #64748b;">
If you didn't create this account, you can safely ignore this email.
</p>
<div class="info-box">
<div class="info-box-title">πŸ” Security Tip</div>
<p style="margin: 5px 0; color: #475569; font-size: 14px;">
Never share your verification link with anyone. MediSync will never ask for your password via email.
</p>
</div>
"""
# --- Medicine Added Email ---
MEDICINE_ADDED_EMAIL_SUBJECT = "βœ“ Medicine Added to Your Schedule"
MEDICINE_ADDED_EMAIL_CONTENT = """
<p class="greeting">Hello, {full_name}! πŸ’Š</p>
<p class="content">
Great news! Your medicine has been successfully added to your schedule.
</p>
<div class="success-box">
<div class="success-box-title">πŸ“‹ Medicine Details</div>
<div class="info-item">πŸ’Š <strong>Medicine:</strong> {medicine_name}</div>
<div class="info-item">πŸ“Š <strong>Dosage:</strong> {dosage}</div>
<div class="info-item">⏰ <strong>Scheduled Time:</strong> {time}</div>
</div>
<p class="content">
You will receive reminders before each scheduled dose. Stay on track with your health goals! 🎯
</p>
<div class="button-container">
<a href="{frontend_url}/dashboard" class="button">View Full Schedule</a>
</div>
"""
# --- Medicine Reminder Email ---
MEDICINE_REMINDER_EMAIL_SUBJECT = "⏰ Medicine Reminder - Time to Take Your Dose"
MEDICINE_REMINDER_EMAIL_CONTENT = """
<p class="greeting">Reminder for {full_name} ⏰</p>
<p class="content">
It's time to take your medicine! Don't forget your health routine.
</p>
<div class="info-box">
<div class="info-box-title">πŸ’Š Dose Information</div>
<div class="info-item">πŸ’Š <strong>Medicine:</strong> {medicine_name}</div>
<div class="info-item">πŸ“Š <strong>Dosage:</strong> {dosage}</div>
<div class="info-item">⏰ <strong>Time:</strong> {time}</div>
</div>
<p class="content">
Please take your medicine as prescribed. Your health is our priority! πŸ’™
</p>
<div class="button-container">
<a href="{frontend_url}/dashboard" class="button">Mark as Taken</a>
</div>
<p class="content" style="font-size: 14px; color: #64748b; text-align: center;">
πŸ’‘ Tip: Set up your dispenser for automatic dispensing to never miss a dose!
</p>
"""
# --- Medicine Missed Email ---
MEDICINE_MISSED_EMAIL_SUBJECT = "⚠️ ALERT: Missed Medicine Notification"
MEDICINE_MISSED_EMAIL_CONTENT = """
<p class="greeting">Important Alert, {full_name} ⚠️</p>
<div class="alert-box">
<div class="alert-box-title">⚠️ Missed Dose Alert</div>
<p style="margin: 10px 0; color: #475569;">
You missed your scheduled medicine dose. Please take it as soon as possible.
</p>
<div class="info-item">πŸ’Š <strong>Medicine:</strong> {medicine_name}</div>
<div class="info-item">πŸ“Š <strong>Dosage:</strong> {dosage}</div>
<div class="info-item">⏰ <strong>Scheduled Time:</strong> {time}</div>
</div>
<p class="content">
If you have any concerns or questions about your medication schedule, please contact your healthcare provider immediately.
</p>
<div class="button-container">
<a href="{frontend_url}/dashboard" class="button">View Schedule</a>
</div>
<div class="info-box">
<div class="info-box-title">πŸ“ž Need Help?</div>
<p style="margin: 5px 0; color: #475569; font-size: 14px;">
Contact your doctor or our support team if you need assistance with your medication schedule.
</p>
</div>
"""
# --- Medicine Updated Email ---
MEDICINE_UPDATED_EMAIL_SUBJECT = "πŸ”„ Medicine Schedule Updated"
MEDICINE_UPDATED_EMAIL_CONTENT = """
<p class="greeting">Update Notification, {full_name} πŸ”„</p>
<p class="content">
Your medicine schedule has been updated successfully.
</p>
<div class="info-box">
<div class="info-box-title">πŸ“‹ Updated Medicine Details</div>
<div class="info-item">πŸ’Š <strong>Medicine:</strong> {medicine_name}</div>
<div class="info-item">πŸ“Š <strong>Dosage:</strong> {dosage}</div>
<div class="info-item">⏰ <strong>New Time:</strong> {time}</div>
</div>
<p class="content">
If you didn't request this change, please contact our support team immediately for assistance.
</p>
<div class="button-container">
<a href="{frontend_url}/dashboard" class="button">Review Changes</a>
</div>
<div class="alert-box">
<div class="alert-box-title">πŸ”’ Security Notice</div>
<p style="margin: 5px 0; color: #475569; font-size: 14px;">
If this update was unauthorized, please contact support immediately at support@MediSync.com
</p>
</div>
"""
# --- Password Reset Email ---
PASSWORD_RESET_EMAIL_SUBJECT = "πŸ” Reset Your Password - MediSync"
PASSWORD_RESET_EMAIL_CONTENT = """
<p class="greeting">Password Reset Request, {full_name} πŸ”</p>
<p class="content">
We received a request to reset your password for your MediSync account.
</p>
<p class="content">
Click the button below to set a new password:
</p>
<div class="button-container">
<a href="{reset_link}" class="button">πŸ”‘ Reset Password</a>
</div>
<p class="content" style="font-size: 14px; color: #64748b;">
If you didn't request a password reset, you can safely ignore this email. Your password will remain unchanged.
</p>
<div class="alert-box">
<div class="alert-box-title">⏱️ Link Expires Soon</div>
<p style="margin: 5px 0; color: #475569; font-size: 14px;">
This password reset link will expire in 1 hour for security reasons.
</p>
</div>
"""
# --- Pre-order Confirmation Email ---
PREORDER_CONFIRMATION_EMAIL_SUBJECT = "πŸŽ‰ Pre-order Confirmed - MediSync"
PREORDER_CONFIRMATION_EMAIL_CONTENT = """
<p class="greeting">Thank You, {full_name}! πŸŽ‰</p>
<p class="content">
We've received your pre-order request for the MediSync AI-Powered Medicine Dispenser!
</p>
<div class="success-box">
<div class="success-box-title">βœ“ What Happens Next?</div>
<p style="margin: 10px 0; color: #475569;">
Our team will review your request and contact you within 24-48 hours with next steps.
</p>
</div>
<p class="content">
You're one step closer to revolutionizing your medication management! πŸš€
</p>
<div class="info-box">
<div class="info-box-title">πŸ“¦ Product Features</div>
<div class="info-item">βœ“ Automated dispensing with smart scheduling</div>
<div class="info-item">βœ“ AI health assistant for medication questions</div>
<div class="info-item">βœ“ Multi-slot system for up to 8 medications</div>
<div class="info-item">βœ“ Smart reminders via SMS & Email</div>
</div>
<p class="content" style="font-size: 14px; color: #64748b;">
Have questions? Feel free to reply to this email anytime!
</p>
"""
# --- Pre-order Notification to Owner ---
PREORDER_NOTIFICATION_OWNER_SUBJECT = "πŸ”” New Pre-order Received"
PREORDER_NOTIFICATION_OWNER_CONTENT = """
<p class="greeting">New Pre-order Alert! 🎯</p>
<p class="content">
A new customer has submitted a pre-order request for MediSync.
</p>
<div class="info-box">
<div class="info-box-title">πŸ‘€ Customer Information</div>
<div class="info-item">πŸ‘€ <strong>Name:</strong> {name}</div>
<div class="info-item">πŸ“ž <strong>Phone:</strong> {phone}</div>
<div class="info-item">πŸ“§ <strong>Email:</strong> {gmail}</div>
<div class="info-item">πŸ’¬ <strong>Message:</strong> {message}</div>
</div>
<div class="button-container">
<a href="{frontend_url}/admin/preorders" class="button">View in Dashboard</a>
</div>
<p class="content" style="font-size: 14px; color: #64748b;">
Please follow up with the customer within 24-48 hours.
</p>
"""
# --- Contact Form Confirmation Email ---
CONTACT_CONFIRMATION_EMAIL_SUBJECT = "βœ“ We've Received Your Message - MediSync"
CONTACT_CONFIRMATION_EMAIL_CONTENT = """
<p class="greeting">Thank You, {name}! πŸ“¬</p>
<p class="content">
We've received your message and appreciate you reaching out to MediSync.
</p>
<div class="info-box">
<div class="info-box-title">πŸ“‹ Message Details</div>
<div class="info-item">πŸ“§ <strong>Subject:</strong> {subject}</div>
<div class="info-item">πŸ’¬ <strong>Your Message:</strong> {message}</div>
</div>
<p class="content">
Our team will review your inquiry and get back to you within 24-48 hours.
</p>
<div class="success-box">
<div class="success-box-title">⏱️ Response Time</div>
<p style="margin: 10px 0; color: #166534;">
We typically respond to all inquiries within 1-2 business days.
</p>
</div>
<p class="content" style="font-size: 14px; color: #64748b;">
If you have any urgent matters, please call us at +1 (234) 567-8900.
</p>
"""
# --- Contact Form Notification to Owner ---
CONTACT_NOTIFICATION_OWNER_SUBJECT = "πŸ“¬ New Contact Form Submission"
CONTACT_NOTIFICATION_OWNER_CONTENT = """
<p class="greeting">New Contact Form Submission! πŸ“¬</p>
<p class="content">
A visitor has submitted a contact form on the MediSync website.
</p>
<div class="info-box">
<div class="info-box-title">πŸ‘€ Contact Information</div>
<div class="info-item">πŸ‘€ <strong>Name:</strong> {name}</div>
<div class="info-item">πŸ“§ <strong>Email:</strong> {email}</div>
<div class="info-item">πŸ“‹ <strong>Subject:</strong> {subject}</div>
<div class="info-item">πŸ’¬ <strong>Message:</strong> {message}</div>
</div>
<div class="button-container">
<a href="{frontend_url}/admin/messages" class="button">View in Dashboard</a>
</div>
<p class="content" style="font-size: 14px; color: #64748b;">
Please respond to this inquiry within 24-48 hours.
</p>
"""
def _send_email(to_email: str, subject: str, html: str):
GMAIL_USER = get_setting("GMAIL_USER")
GMAIL_PASS = get_setting("GMAIL_PASS")
if not GMAIL_USER or not GMAIL_PASS:
print("Gmail credentials not set.")
# We don't raise exception to avoid crashing the app if credentials are missing,
# but normally we should. However, since this is async background task usually, printing is safe.
# But let's log and return.
return
# Create the root message and fill in the from, to, and subject headers
msg = MIMEMultipart("related") # Changed to 'related' to embed images
msg["Subject"] = subject
msg["From"] = GMAIL_USER
msg["To"] = to_email
# Attach the HTML part
msg.attach(MIMEText(html, "html"))
# Attach the image
image_path = "mediflow-logo-trans.png"
try:
with open(image_path, "rb") as img_file:
img_data = img_file.read()
img = MIMEImage(img_data, name=os.path.basename(image_path))
img.add_header("Content-ID", "<mediflow-logo>") # Content-ID for referencing in HTML
msg.attach(img)
except FileNotFoundError:
print(f"Warning: Logo image not found at {image_path}. Email will be sent without logo.")
except Exception as e:
print(f"Error embedding logo image: {e}")
try:
with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server:
server.login(GMAIL_USER, GMAIL_PASS)
server.sendmail(GMAIL_USER, to_email, msg.as_string())
except Exception as e:
print(f"Failed to send email: {e}")
raise
async def send_verification_email(to_email: str, full_name: str, verification_link: str):
content = ACCOUNT_VERIFICATION_EMAIL_CONTENT.format(
full_name=full_name,
verification_link=verification_link
)
html = EMAIL_BASE_TEMPLATE.format(content=content)
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, _send_email, to_email, ACCOUNT_VERIFICATION_EMAIL_SUBJECT, html)
async def send_password_reset_email(to_email: str, full_name: str, reset_link: str):
content = PASSWORD_RESET_EMAIL_CONTENT.format(
full_name=full_name,
reset_link=reset_link
)
html = EMAIL_BASE_TEMPLATE.format(content=content)
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, _send_email, to_email, PASSWORD_RESET_EMAIL_SUBJECT, html)
async def send_preorder_confirmation_email(to_email: str, full_name: str):
content = PREORDER_CONFIRMATION_EMAIL_CONTENT.format(full_name=full_name)
html = EMAIL_BASE_TEMPLATE.format(content=content)
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, _send_email, to_email, PREORDER_CONFIRMATION_EMAIL_SUBJECT, html)
async def send_preorder_notification_to_owner(name: str, phone: str, gmail: str, message: str):
frontend_url = get_frontend_url()
content = PREORDER_NOTIFICATION_OWNER_CONTENT.format(
name=name,
phone=phone,
gmail=gmail,
message=message or "No message provided",
frontend_url=frontend_url
)
html = EMAIL_BASE_TEMPLATE.format(content=content)
loop = asyncio.get_event_loop()
await loop.run_in_executor(
None,
_send_email,
"birdskeener@gmail.com",
PREORDER_NOTIFICATION_OWNER_SUBJECT,
html
)
async def send_medicine_added_email(to_email: str, full_name: str, medicine_name: str, dosage: str, time: str):
frontend_url = get_frontend_url()
content = MEDICINE_ADDED_EMAIL_CONTENT.format(
full_name=full_name,
medicine_name=medicine_name,
dosage=dosage,
time=time,
frontend_url=frontend_url
)
html = EMAIL_BASE_TEMPLATE.format(content=content)
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, _send_email, to_email, MEDICINE_ADDED_EMAIL_SUBJECT, html)
async def send_medicine_reminder_email(to_email: str, full_name: str, medicine_name: str, dosage: str, time: str):
frontend_url = get_frontend_url()
content = MEDICINE_REMINDER_EMAIL_CONTENT.format(
full_name=full_name,
medicine_name=medicine_name,
dosage=dosage,
time=time,
frontend_url=frontend_url
)
html = EMAIL_BASE_TEMPLATE.format(content=content)
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, _send_email, to_email, MEDICINE_REMINDER_EMAIL_SUBJECT, html)
async def send_medicine_missed_email(to_email: str, full_name: str, medicine_name: str, dosage: str, time: str):
frontend_url = get_frontend_url()
content = MEDICINE_MISSED_EMAIL_CONTENT.format(
full_name=full_name,
medicine_name=medicine_name,
dosage=dosage,
time=time,
frontend_url=frontend_url
)
html = EMAIL_BASE_TEMPLATE.format(content=content)
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, _send_email, to_email, MEDICINE_MISSED_EMAIL_SUBJECT, html)
async def send_medicine_updated_email(to_email: str, full_name: str, medicine_name: str, dosage: str, time: str):
frontend_url = get_frontend_url()
content = MEDICINE_UPDATED_EMAIL_CONTENT.format(
full_name=full_name,
medicine_name=medicine_name,
dosage=dosage,
time=time,
frontend_url=frontend_url
)
html = EMAIL_BASE_TEMPLATE.format(content=content)
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, _send_email, to_email, MEDICINE_UPDATED_EMAIL_SUBJECT, html)
async def send_contact_confirmation_email(to_email: str, name: str, subject: str, message: str):
content = CONTACT_CONFIRMATION_EMAIL_CONTENT.format(
name=name,
subject=subject,
message=message
)
html = EMAIL_BASE_TEMPLATE.format(content=content)
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, _send_email, to_email, CONTACT_CONFIRMATION_EMAIL_SUBJECT, html)
async def send_contact_notification_to_owner(name: str, email: str, subject: str, message: str):
frontend_url = get_frontend_url()
content = CONTACT_NOTIFICATION_OWNER_CONTENT.format(
name=name,
email=email,
subject=subject,
message=message,
frontend_url=frontend_url
)
html = EMAIL_BASE_TEMPLATE.format(content=content)
loop = asyncio.get_event_loop()
await loop.run_in_executor(
None,
_send_email,
"birdskeener@gmail.com",
CONTACT_NOTIFICATION_OWNER_SUBJECT,
html
)
# --- Subscription Approval Email ---
SUBSCRIPTION_APPROVAL_EMAIL_SUBJECT = "πŸŽ‰ Subscription Approved - MediSync"
SUBSCRIPTION_APPROVAL_EMAIL_CONTENT = """
<p class="greeting">Congratulations, {full_name}! πŸŽ‰</p>
<p class="content">
Your subscription to MediSync has been approved successfully!
</p>
<div class="success-box">
<div class="success-box-title">βœ“ Subscription Details</div>
<div class="info-item">πŸ“… <strong>Plan:</strong> {plan}</div>
<div class="info-item">⏳ <strong>Valid Until:</strong> {end_date}</div>
<div class="info-item">βœ… <strong>Status:</strong> Active</div>
</div>
<p class="content">
You now have full access to all premium features. Thank you for choosing MediSync!
</p>
<div class="button-container">
<a href="{frontend_url}/dashboard" class="button">Go to Dashboard</a>
</div>
"""
async def send_subscription_approval_email(to_email: str, full_name: str, plan: str, end_date: str):
frontend_url = get_frontend_url()
content = SUBSCRIPTION_APPROVAL_EMAIL_CONTENT.format(
full_name=full_name,
plan=plan.capitalize(),
end_date=end_date,
frontend_url=frontend_url
)
html = EMAIL_BASE_TEMPLATE.format(content=content)
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, _send_email, to_email, SUBSCRIPTION_APPROVAL_EMAIL_SUBJECT, html)
# --- Payment Success Email ---
PAYMENT_SUCCESS_EMAIL_SUBJECT = "βœ… Payment Successful - MediSync"
PAYMENT_SUCCESS_EMAIL_CONTENT = """
<p class="greeting">Payment Received, {full_name}! βœ…</p>
<p class="content">
Thank you for your payment. Your transaction was successful and your subscription is now active!
</p>
<div class="success-box">
<div class="success-box-title">🧾 Transaction Receipt</div>
<div class="info-item">πŸ’³ <strong>Transaction ID:</strong> {transaction_id}</div>
<div class="info-item">πŸ“… <strong>Plan:</strong> {plan_name}</div>
<div class="info-item">πŸ’° <strong>Amount:</strong> {amount}</div>
<div class="info-item">πŸ—“οΈ <strong>Date:</strong> {date}</div>
</div>
<p class="content">
You can now enjoy all the benefits of your {plan_name}.
</p>
<div class="button-container">
<a href="{frontend_url}/dashboard" class="button">Go to Dashboard</a>
</div>
<p class="content" style="font-size: 14px; color: #64748b; text-align: center;">
A copy of this receipt has been saved to your account.
</p>
"""
async def send_payment_success_email(to_email: str, full_name: str, transaction_id: str, plan_name: str, amount: str, date: str):
frontend_url = get_frontend_url()
content = PAYMENT_SUCCESS_EMAIL_CONTENT.format(
full_name=full_name,
transaction_id=transaction_id,
plan_name=plan_name,
amount=amount,
date=date,
frontend_url=frontend_url
)
html = EMAIL_BASE_TEMPLATE.format(content=content)
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, _send_email, to_email, PAYMENT_SUCCESS_EMAIL_SUBJECT, html)