|
import base64 |
|
import aiohttp |
|
from fastapi import APIRouter, HTTPException |
|
from pydantic import BaseModel |
|
from google.auth.transport.requests import Request |
|
from google.oauth2.credentials import Credentials |
|
from email.mime.text import MIMEText |
|
from email.utils import formataddr |
|
|
|
router = APIRouter() |
|
|
|
CLIENT_ID = "1033810476410-cd4t2ojekl2qmek6o0na1uj9gcdonu2d.apps.googleusercontent.com" |
|
CLIENT_SECRET = "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" |
|
REFRESH_TOKEN = "1//048eSNFimtH-5CgYIARAAGAQSNwF-L9IrnsvcPX_TMwXfyaTTtfgeMlANP3uqoKw2IK7Ww0eB50EXYGMEtwrTDEfT157PgoC1J9s" |
|
EMAIL_ADDRESS = "[email protected]" |
|
SENDER_NAME = "ClosetCoach" |
|
|
|
SCOPES = ['https://www.googleapis.com/auth/gmail.send'] |
|
|
|
class EmailRequest(BaseModel): |
|
to: str |
|
subject: str |
|
type: str |
|
|
|
def get_access_token(): |
|
creds = Credentials( |
|
None, |
|
refresh_token=REFRESH_TOKEN, |
|
token_uri='https://oauth2.googleapis.com/token', |
|
client_id=CLIENT_ID, |
|
client_secret=CLIENT_SECRET, |
|
scopes=SCOPES, |
|
) |
|
creds.refresh(Request()) |
|
return creds.token |
|
|
|
def generate_email_html(email_type: str, to: str) -> str: |
|
|
|
if email_type == "welcome": |
|
return """ |
|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Welcome to ClosetCoach</title> |
|
<style> |
|
* { |
|
margin: 0; |
|
padding: 0; |
|
box-sizing: border-box; |
|
} |
|
|
|
body { |
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; |
|
background-color: #ffffff; |
|
color: #1d1d1f; |
|
line-height: 1.6; |
|
} |
|
|
|
.email-container { |
|
max-width: 600px; |
|
margin: 0 auto; |
|
background-color: #ffffff; |
|
} |
|
|
|
.header { |
|
text-align: center; |
|
padding: 60px 40px 40px; |
|
} |
|
|
|
.logo { |
|
font-size: 28px; |
|
font-weight: 700; |
|
color: #6b46c1; |
|
letter-spacing: -0.5px; |
|
} |
|
|
|
.hero-section { |
|
text-align: center; |
|
padding: 0 40px 60px; |
|
} |
|
|
|
.hero-image { |
|
width: 100%; |
|
max-width: 280px; |
|
height: 200px; |
|
object-fit: cover; |
|
margin: 0 auto 50px; |
|
border-radius: 20px; |
|
box-shadow: 0 20px 40px rgba(107, 70, 193, 0.1); |
|
} |
|
|
|
.headline { |
|
font-size: 36px; |
|
font-weight: 700; |
|
color: #1d1d1f; |
|
margin-bottom: 24px; |
|
line-height: 1.2; |
|
letter-spacing: -0.8px; |
|
} |
|
|
|
.subheadline { |
|
font-size: 20px; |
|
font-weight: 400; |
|
color: #6e6e73; |
|
margin-bottom: 50px; |
|
line-height: 1.4; |
|
max-width: 480px; |
|
margin-left: auto; |
|
margin-right: auto; |
|
} |
|
|
|
.cta-button { |
|
display: inline-block; |
|
background: linear-gradient(135deg, #6b46c1 0%, #8b5cf6 100%); |
|
color: #ffffff; |
|
text-decoration: none; |
|
padding: 16px 40px; |
|
border-radius: 50px; |
|
font-size: 18px; |
|
font-weight: 600; |
|
letter-spacing: 0.2px; |
|
transition: all 0.3s ease; |
|
box-shadow: 0 8px 24px rgba(107, 70, 193, 0.3); |
|
margin-bottom: 60px; |
|
} |
|
|
|
.cta-button:hover { |
|
transform: translateY(-2px); |
|
box-shadow: 0 12px 32px rgba(107, 70, 193, 0.4); |
|
} |
|
|
|
.footer { |
|
text-align: center; |
|
padding: 40px; |
|
border-top: 1px solid #f5f5f7; |
|
margin-top: 40px; |
|
} |
|
|
|
.footer-text { |
|
font-size: 14px; |
|
color: #86868b; |
|
margin-bottom: 16px; |
|
} |
|
|
|
@media (max-width: 480px) { |
|
.header { |
|
padding: 40px 20px 20px; |
|
} |
|
|
|
.hero-section { |
|
padding: 0 20px 40px; |
|
} |
|
|
|
.headline { |
|
font-size: 28px; |
|
} |
|
|
|
.subheadline { |
|
font-size: 18px; |
|
} |
|
|
|
.footer { |
|
padding: 30px 20px; |
|
} |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="email-container"> |
|
<!-- Header --> |
|
<div class="header"> |
|
<div class="logo">ClosetCoach</div> |
|
</div> |
|
|
|
<!-- Hero Section --> |
|
<div class="hero-section"> |
|
<img src="https://huggingface.co/spaces/habulaj/connect/resolve/main/brazuca.jpg" alt="Style transformation illustration" class="hero-image"> |
|
|
|
<h1 class="headline">Welcome to your style journey</h1> |
|
|
|
<p class="subheadline"> |
|
Connect with professional stylists who understand your unique style and help you create looks that make you feel confident and authentic. |
|
</p> |
|
|
|
<a href="https://ameddes.com/onboarding/splash" class="cta-button">Discover New Stylists</a> |
|
</div> |
|
|
|
<!-- Footer --> |
|
<div class="footer"> |
|
<p class="footer-text"> |
|
You're receiving this email because you signed up for ClosetCoach.<br> |
|
Ready to transform your style? Let's get started! |
|
</p> |
|
|
|
<p class="footer-text" style="margin-top: 24px;"> |
|
© 2025 ClosetCoach. All rights reserved. |
|
</p> |
|
</div> |
|
</div> |
|
</body> |
|
</html> |
|
""" |
|
elif email_type == "stylistwelcome": |
|
return """ |
|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Welcome to ClosetCoach</title> |
|
<style> |
|
* { |
|
margin: 0; |
|
padding: 0; |
|
box-sizing: border-box; |
|
} |
|
|
|
body { |
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; |
|
background-color: #ffffff; |
|
color: #1d1d1f; |
|
line-height: 1.6; |
|
} |
|
|
|
.email-container { |
|
max-width: 600px; |
|
margin: 0 auto; |
|
background-color: #ffffff; |
|
} |
|
|
|
.header { |
|
text-align: center; |
|
padding: 60px 40px 40px; |
|
} |
|
|
|
.logo { |
|
font-size: 28px; |
|
font-weight: 700; |
|
color: #6b46c1; |
|
letter-spacing: -0.5px; |
|
} |
|
|
|
.hero-section { |
|
text-align: center; |
|
padding: 0 40px 60px; |
|
} |
|
|
|
.hero-image { |
|
width: 100%; |
|
max-width: 280px; |
|
height: 200px; |
|
object-fit: cover; |
|
margin: 0 auto 50px; |
|
border-radius: 20px; |
|
box-shadow: 0 20px 40px rgba(107, 70, 193, 0.1); |
|
} |
|
|
|
.headline { |
|
font-size: 36px; |
|
font-weight: 700; |
|
color: #1d1d1f; |
|
margin-bottom: 24px; |
|
line-height: 1.2; |
|
letter-spacing: -0.8px; |
|
} |
|
|
|
.subheadline { |
|
font-size: 20px; |
|
font-weight: 400; |
|
color: #6e6e73; |
|
margin-bottom: 30px; |
|
line-height: 1.4; |
|
max-width: 480px; |
|
margin-left: auto; |
|
margin-right: auto; |
|
} |
|
|
|
.status-box { |
|
background-color: #fef3c7; |
|
border: 1px solid #fbbf24; |
|
border-radius: 12px; |
|
padding: 20px; |
|
margin: 30px 0; |
|
max-width: 480px; |
|
margin-left: auto; |
|
margin-right: auto; |
|
} |
|
|
|
.status-title { |
|
font-size: 18px; |
|
font-weight: 600; |
|
color: #92400e; |
|
margin-bottom: 8px; |
|
} |
|
|
|
.status-text { |
|
font-size: 16px; |
|
color: #92400e; |
|
line-height: 1.5; |
|
} |
|
|
|
.next-steps { |
|
font-size: 18px; |
|
font-weight: 400; |
|
color: #6e6e73; |
|
margin: 30px 0; |
|
line-height: 1.4; |
|
max-width: 480px; |
|
margin-left: auto; |
|
margin-right: auto; |
|
} |
|
|
|
.cta-button { |
|
display: inline-block; |
|
background: linear-gradient(135deg, #6b46c1 0%, #8b5cf6 100%); |
|
color: #ffffff; |
|
text-decoration: none; |
|
padding: 16px 40px; |
|
border-radius: 50px; |
|
font-size: 18px; |
|
font-weight: 600; |
|
letter-spacing: 0.2px; |
|
transition: all 0.3s ease; |
|
box-shadow: 0 8px 24px rgba(107, 70, 193, 0.3); |
|
margin-bottom: 60px; |
|
} |
|
|
|
.cta-button:hover { |
|
transform: translateY(-2px); |
|
box-shadow: 0 12px 32px rgba(107, 70, 193, 0.4); |
|
} |
|
|
|
.footer { |
|
text-align: center; |
|
padding: 40px; |
|
border-top: 1px solid #f5f5f7; |
|
margin-top: 40px; |
|
} |
|
|
|
.footer-text { |
|
font-size: 14px; |
|
color: #86868b; |
|
margin-bottom: 16px; |
|
} |
|
|
|
@media (max-width: 480px) { |
|
.header { |
|
padding: 40px 20px 20px; |
|
} |
|
|
|
.hero-section { |
|
padding: 0 20px 40px; |
|
} |
|
|
|
.headline { |
|
font-size: 28px; |
|
} |
|
|
|
.subheadline { |
|
font-size: 18px; |
|
} |
|
|
|
.footer { |
|
padding: 30px 20px; |
|
} |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="email-container"> |
|
<!-- Header --> |
|
<div class="header"> |
|
<div class="logo">ClosetCoach</div> |
|
</div> |
|
|
|
<!-- Hero Section --> |
|
<div class="hero-section"> |
|
<img src="https://huggingface.co/spaces/habulaj/connect/resolve/main/brazuca.jpg" alt="Style transformation illustration" class="hero-image"> |
|
|
|
<h1 class="headline">Welcome to ClosetCoach</h1> |
|
|
|
<p class="subheadline"> |
|
Thank you for joining our community of professional stylists! We're excited to have you on board. |
|
</p> |
|
|
|
<div class="status-box"> |
|
<div class="status-title">📋 Account Under Review</div> |
|
<div class="status-text"> |
|
Your stylist profile is currently being reviewed by our team. We'll notify you via email once your account is approved and ready to connect with clients. |
|
</div> |
|
</div> |
|
|
|
<p class="next-steps"> |
|
Grab a coffee and relax! Our review process is typically quick, and we'll have you connected with clients in no time. |
|
</p> |
|
</div> |
|
|
|
<!-- Footer --> |
|
<div class="footer"> |
|
<p class="footer-text"> |
|
You're receiving this email because you signed up as a stylist on ClosetCoach.<br> |
|
We'll update you on your account status soon! |
|
</p> |
|
|
|
<p class="footer-text" style="margin-top: 24px;"> |
|
© 2025 ClosetCoach. All rights reserved. |
|
</p> |
|
</div> |
|
</div> |
|
</body> |
|
</html> |
|
""" |
|
elif email_type == "stylistapprove": |
|
return """ |
|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>You're Approved! - ClosetCoach</title> |
|
<style> |
|
* { |
|
margin: 0; |
|
padding: 0; |
|
box-sizing: border-box; |
|
} |
|
|
|
body { |
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; |
|
background-color: #ffffff; |
|
color: #1d1d1f; |
|
line-height: 1.6; |
|
} |
|
|
|
.email-container { |
|
max-width: 600px; |
|
margin: 0 auto; |
|
background-color: #ffffff; |
|
} |
|
|
|
.header { |
|
text-align: center; |
|
padding: 60px 40px 40px; |
|
} |
|
|
|
.logo { |
|
font-size: 28px; |
|
font-weight: 700; |
|
color: #6b46c1; |
|
letter-spacing: -0.5px; |
|
} |
|
|
|
.hero-section { |
|
text-align: center; |
|
padding: 0 40px 60px; |
|
} |
|
|
|
.hero-image { |
|
width: 100%; |
|
max-width: 280px; |
|
height: 200px; |
|
object-fit: cover; |
|
margin: 0 auto 50px; |
|
border-radius: 20px; |
|
box-shadow: 0 20px 40px rgba(107, 70, 193, 0.1); |
|
} |
|
|
|
.headline { |
|
font-size: 36px; |
|
font-weight: 700; |
|
color: #1d1d1f; |
|
margin-bottom: 24px; |
|
line-height: 1.2; |
|
letter-spacing: -0.8px; |
|
} |
|
|
|
.subheadline { |
|
font-size: 20px; |
|
font-weight: 400; |
|
color: #6e6e73; |
|
margin-bottom: 30px; |
|
line-height: 1.4; |
|
max-width: 480px; |
|
margin-left: auto; |
|
margin-right: auto; |
|
} |
|
|
|
.status-box { |
|
background-color: #dcfce7; |
|
border: 1px solid #22c55e; |
|
border-radius: 12px; |
|
padding: 20px; |
|
margin: 30px 0; |
|
max-width: 480px; |
|
margin-left: auto; |
|
margin-right: auto; |
|
} |
|
|
|
.status-title { |
|
font-size: 18px; |
|
font-weight: 600; |
|
color: #166534; |
|
margin-bottom: 8px; |
|
} |
|
|
|
.status-text { |
|
font-size: 16px; |
|
color: #166534; |
|
line-height: 1.5; |
|
} |
|
|
|
.next-steps { |
|
font-size: 18px; |
|
font-weight: 400; |
|
color: #6e6e73; |
|
margin: 30px 0; |
|
line-height: 1.4; |
|
max-width: 480px; |
|
margin-left: auto; |
|
margin-right: auto; |
|
} |
|
|
|
.cta-button { |
|
display: inline-block; |
|
background: linear-gradient(135deg, #6b46c1 0%, #8b5cf6 100%); |
|
color: #ffffff; |
|
text-decoration: none; |
|
padding: 16px 40px; |
|
border-radius: 50px; |
|
font-size: 18px; |
|
font-weight: 600; |
|
letter-spacing: 0.2px; |
|
transition: all 0.3s ease; |
|
box-shadow: 0 8px 24px rgba(107, 70, 193, 0.3); |
|
margin-bottom: 60px; |
|
} |
|
|
|
.cta-button:hover { |
|
transform: translateY(-2px); |
|
box-shadow: 0 12px 32px rgba(107, 70, 193, 0.4); |
|
} |
|
|
|
.footer { |
|
text-align: center; |
|
padding: 40px; |
|
border-top: 1px solid #f5f5f7; |
|
margin-top: 40px; |
|
} |
|
|
|
.footer-text { |
|
font-size: 14px; |
|
color: #86868b; |
|
margin-bottom: 16px; |
|
} |
|
|
|
@media (max-width: 480px) { |
|
.header { |
|
padding: 40px 20px 20px; |
|
} |
|
|
|
.hero-section { |
|
padding: 0 20px 40px; |
|
} |
|
|
|
.headline { |
|
font-size: 28px; |
|
} |
|
|
|
.subheadline { |
|
font-size: 18px; |
|
} |
|
|
|
.footer { |
|
padding: 30px 20px; |
|
} |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="email-container"> |
|
<!-- Header --> |
|
<div class="header"> |
|
<div class="logo">ClosetCoach</div> |
|
</div> |
|
|
|
<!-- Hero Section --> |
|
<div class="hero-section"> |
|
<img src="https://huggingface.co/spaces/habulaj/connect/resolve/main/approve.png" alt="Approved illustration" class="hero-image"> |
|
|
|
<h1 class="headline">Congratulations! You're approved</h1> |
|
|
|
<p class="subheadline"> |
|
Your stylist profile has been reviewed and approved. Now it's time to complete your account setup and start earning with your styling expertise. |
|
</p> |
|
|
|
<div class="status-box"> |
|
<div class="status-title">🎉 Account Activated</div> |
|
<div class="status-text"> |
|
Your stylist account is now live! Complete your setup to start receiving payments and connect with clients. |
|
</div> |
|
</div> |
|
|
|
<p class="next-steps"> |
|
Before you start styling, you'll need to configure your banking information, set your service prices, and finalize your payment preferences to begin earning. |
|
</p> |
|
|
|
<a href="https://ameddes.com/onboarding/splash" class="cta-button">Complete Account Setup</a> |
|
</div> |
|
|
|
<!-- Footer --> |
|
<div class="footer"> |
|
<p class="footer-text"> |
|
You're receiving this email because your ClosetCoach stylist account has been approved.<br> |
|
Complete your setup to start your styling journey! |
|
</p> |
|
|
|
<p class="footer-text" style="margin-top: 24px;"> |
|
© 2025 ClosetCoach. All rights reserved. |
|
</p> |
|
</div> |
|
</div> |
|
</body> |
|
</html> |
|
""" |
|
elif email_type == "stylistnotapproved": |
|
return """ |
|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Application Update - ClosetCoach</title> |
|
<style> |
|
* { |
|
margin: 0; |
|
padding: 0; |
|
box-sizing: border-box; |
|
} |
|
|
|
body { |
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; |
|
background-color: #ffffff; |
|
color: #1d1d1f; |
|
line-height: 1.6; |
|
} |
|
|
|
.email-container { |
|
max-width: 600px; |
|
margin: 0 auto; |
|
background-color: #ffffff; |
|
} |
|
|
|
.header { |
|
text-align: center; |
|
padding: 60px 40px 40px; |
|
} |
|
|
|
.logo { |
|
font-size: 28px; |
|
font-weight: 700; |
|
color: #6b46c1; |
|
letter-spacing: -0.5px; |
|
} |
|
|
|
.hero-section { |
|
text-align: center; |
|
padding: 0 40px 60px; |
|
} |
|
|
|
.hero-image { |
|
width: 100%; |
|
max-width: 280px; |
|
height: 200px; |
|
object-fit: cover; |
|
margin: 0 auto 50px; |
|
border-radius: 20px; |
|
box-shadow: 0 20px 40px rgba(107, 70, 193, 0.1); |
|
} |
|
|
|
.headline { |
|
font-size: 36px; |
|
font-weight: 700; |
|
color: #1d1d1f; |
|
margin-bottom: 24px; |
|
line-height: 1.2; |
|
letter-spacing: -0.8px; |
|
} |
|
|
|
.subheadline { |
|
font-size: 20px; |
|
font-weight: 400; |
|
color: #6e6e73; |
|
margin-bottom: 30px; |
|
line-height: 1.4; |
|
max-width: 480px; |
|
margin-left: auto; |
|
margin-right: auto; |
|
} |
|
|
|
.status-box { |
|
background-color: #fef2f2; |
|
border: 1px solid #f87171; |
|
border-radius: 12px; |
|
padding: 20px; |
|
margin: 30px 0; |
|
max-width: 480px; |
|
margin-left: auto; |
|
margin-right: auto; |
|
} |
|
|
|
.status-title { |
|
font-size: 18px; |
|
font-weight: 600; |
|
color: #dc2626; |
|
margin-bottom: 8px; |
|
} |
|
|
|
.status-text { |
|
font-size: 16px; |
|
color: #dc2626; |
|
line-height: 1.5; |
|
} |
|
|
|
.next-steps { |
|
font-size: 18px; |
|
font-weight: 400; |
|
color: #6e6e73; |
|
margin: 30px 0; |
|
line-height: 1.4; |
|
max-width: 480px; |
|
margin-left: auto; |
|
margin-right: auto; |
|
} |
|
|
|
.cta-button { |
|
display: inline-block; |
|
background: linear-gradient(135deg, #6b46c1 0%, #8b5cf6 100%); |
|
color: #ffffff; |
|
text-decoration: none; |
|
padding: 16px 40px; |
|
border-radius: 50px; |
|
font-size: 18px; |
|
font-weight: 600; |
|
letter-spacing: 0.2px; |
|
transition: all 0.3s ease; |
|
box-shadow: 0 8px 24px rgba(107, 70, 193, 0.3); |
|
margin-bottom: 60px; |
|
} |
|
|
|
.cta-button:hover { |
|
transform: translateY(-2px); |
|
box-shadow: 0 12px 32px rgba(107, 70, 193, 0.4); |
|
} |
|
|
|
.footer { |
|
text-align: center; |
|
padding: 40px; |
|
border-top: 1px solid #f5f5f7; |
|
margin-top: 40px; |
|
} |
|
|
|
.footer-text { |
|
font-size: 14px; |
|
color: #86868b; |
|
margin-bottom: 16px; |
|
} |
|
|
|
@media (max-width: 480px) { |
|
.header { |
|
padding: 40px 20px 20px; |
|
} |
|
|
|
.hero-section { |
|
padding: 0 20px 40px; |
|
} |
|
|
|
.headline { |
|
font-size: 28px; |
|
} |
|
|
|
.subheadline { |
|
font-size: 18px; |
|
} |
|
|
|
.footer { |
|
padding: 30px 20px; |
|
} |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="email-container"> |
|
<!-- Header --> |
|
<div class="header"> |
|
<div class="logo">ClosetCoach</div> |
|
</div> |
|
|
|
<!-- Hero Section --> |
|
<div class="hero-section"> |
|
<img src="https://huggingface.co/spaces/habulaj/connect/resolve/main/approve.png" alt="Application update illustration" class="hero-image"> |
|
|
|
<h1 class="headline">Application Update</h1> |
|
|
|
<p class="subheadline"> |
|
Thank you for your interest in becoming a ClosetCoach stylist. After careful review, we're unable to approve your application at this time. |
|
</p> |
|
|
|
<div class="status-box"> |
|
<div class="status-title">❌ Application Not Approved</div> |
|
<div class="status-text"> |
|
Your stylist application has been reviewed and was not approved based on our current requirements and standards. |
|
</div> |
|
</div> |
|
|
|
<p class="next-steps"> |
|
For detailed feedback and specific reasons regarding your application, please open the ClosetCoach app and check your account notifications. |
|
</p> |
|
|
|
<a href="https://ameddes.com/onboarding/splash" class="cta-button">Open App for Details</a> |
|
</div> |
|
|
|
<!-- Footer --> |
|
<div class="footer"> |
|
<p class="footer-text"> |
|
You're receiving this email regarding your ClosetCoach stylist application.<br> |
|
We appreciate your interest in joining our platform. |
|
</p> |
|
|
|
<p class="footer-text" style="margin-top: 24px;"> |
|
© 2025 ClosetCoach. All rights reserved. |
|
</p> |
|
</div> |
|
</div> |
|
</body> |
|
</html> |
|
""" |
|
elif email_type == "newsubscriber": |
|
return """ |
|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>New Subscriber - ClosetCoach</title> |
|
<style> |
|
* { |
|
margin: 0; |
|
padding: 0; |
|
box-sizing: border-box; |
|
} |
|
body { |
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; |
|
background-color: #ffffff; |
|
color: #1d1d1f; |
|
line-height: 1.6; |
|
} |
|
.email-container { |
|
max-width: 600px; |
|
margin: 0 auto; |
|
background-color: #ffffff; |
|
} |
|
.header { |
|
text-align: center; |
|
padding: 60px 40px 40px; |
|
} |
|
.logo { |
|
font-size: 28px; |
|
font-weight: 700; |
|
color: #6b46c1; |
|
letter-spacing: -0.5px; |
|
} |
|
.hero-section { |
|
text-align: center; |
|
padding: 0 40px 60px; |
|
} |
|
.hero-image { |
|
width: 100%; |
|
max-width: 280px; |
|
height: 200px; |
|
object-fit: cover; |
|
margin: 0 auto 50px; |
|
border-radius: 20px; |
|
box-shadow: 0 20px 40px rgba(107, 70, 193, 0.1); |
|
} |
|
.celebration-badge { |
|
display: inline-block; |
|
background: linear-gradient(135deg, #10b981 0%, #059669 100%); |
|
color: #ffffff; |
|
padding: 8px 20px; |
|
border-radius: 25px; |
|
font-size: 14px; |
|
font-weight: 600; |
|
text-transform: uppercase; |
|
letter-spacing: 0.5px; |
|
margin-bottom: 30px; |
|
} |
|
.headline { |
|
font-size: 36px; |
|
font-weight: 700; |
|
color: #1d1d1f; |
|
margin-bottom: 24px; |
|
line-height: 1.2; |
|
letter-spacing: -0.8px; |
|
} |
|
.subheadline { |
|
font-size: 20px; |
|
font-weight: 400; |
|
color: #6e6e73; |
|
margin-bottom: 30px; |
|
line-height: 1.4; |
|
max-width: 480px; |
|
margin-left: auto; |
|
margin-right: auto; |
|
} |
|
.highlight-box { |
|
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%); |
|
border-radius: 16px; |
|
padding: 32px; |
|
margin: 40px 0; |
|
border-left: 4px solid #6b46c1; |
|
} |
|
.highlight-text { |
|
font-size: 18px; |
|
font-weight: 600; |
|
color: #1d1d1f; |
|
margin-bottom: 12px; |
|
} |
|
.highlight-subtext { |
|
font-size: 16px; |
|
color: #64748b; |
|
line-height: 1.5; |
|
} |
|
.cta-button { |
|
display: inline-block; |
|
background: linear-gradient(135deg, #6b46c1 0%, #8b5cf6 100%); |
|
color: #ffffff; |
|
text-decoration: none; |
|
padding: 16px 40px; |
|
border-radius: 50px; |
|
font-size: 18px; |
|
font-weight: 600; |
|
letter-spacing: 0.2px; |
|
transition: all 0.3s ease; |
|
box-shadow: 0 8px 24px rgba(107, 70, 193, 0.3); |
|
margin-bottom: 40px; |
|
} |
|
.cta-button:hover { |
|
transform: translateY(-2px); |
|
box-shadow: 0 12px 32px rgba(107, 70, 193, 0.4); |
|
} |
|
.tips-section { |
|
background-color: #fafafa; |
|
border-radius: 20px; |
|
padding: 32px; |
|
margin: 40px 0; |
|
} |
|
.tips-title { |
|
font-size: 20px; |
|
font-weight: 700; |
|
color: #1d1d1f; |
|
margin-bottom: 20px; |
|
text-align: center; |
|
} |
|
.tip-item { |
|
display: flex; |
|
align-items: flex-start; |
|
margin-bottom: 16px; |
|
padding: 16px; |
|
background-color: #ffffff; |
|
border-radius: 12px; |
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
|
} |
|
.tip-icon { |
|
width: 24px; |
|
height: 24px; |
|
background: linear-gradient(135deg, #6b46c1 0%, #8b5cf6 100%); |
|
border-radius: 50%; |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
margin-right: 16px; |
|
flex-shrink: 0; |
|
color: #ffffff; |
|
font-weight: 600; |
|
font-size: 12px; |
|
} |
|
.tip-text { |
|
font-size: 16px; |
|
color: #374151; |
|
line-height: 1.5; |
|
} |
|
.footer { |
|
text-align: center; |
|
padding: 40px; |
|
border-top: 1px solid #f5f5f7; |
|
margin-top: 40px; |
|
} |
|
.footer-text { |
|
font-size: 14px; |
|
color: #86868b; |
|
margin-bottom: 16px; |
|
} |
|
@media (max-width: 480px) { |
|
.header { |
|
padding: 40px 20px 20px; |
|
} |
|
.hero-section { |
|
padding: 0 20px 40px; |
|
} |
|
.headline { |
|
font-size: 28px; |
|
} |
|
.subheadline { |
|
font-size: 18px; |
|
} |
|
.highlight-box, .tips-section { |
|
padding: 24px; |
|
margin: 30px 0; |
|
} |
|
.footer { |
|
padding: 30px 20px; |
|
} |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="email-container"> |
|
<!-- Header --> |
|
<div class="header"> |
|
<div class="logo">ClosetCoach</div> |
|
</div> |
|
|
|
<!-- Hero Section --> |
|
<div class="hero-section"> |
|
<div class="celebration-badge">🎉 New Subscriber</div> |
|
|
|
<img src="https://huggingface.co/spaces/habulaj/connect/resolve/main/subscriber.png" alt="New subscriber celebration" class="hero-image"> |
|
|
|
<h1 class="headline">Congratulations! You have a new subscriber</h1> |
|
|
|
<p class="subheadline"> |
|
Someone just discovered your amazing style expertise and decided to follow your fashion journey. Your influence is growing! |
|
</p> |
|
|
|
<div class="highlight-box"> |
|
<div class="highlight-text">Your Style Community is Expanding</div> |
|
<div class="highlight-subtext"> |
|
This new subscriber can now chat with you directly, view your personal portfolio, and book styling sessions. They'll also see all your latest portfolio posts alongside your other followers! |
|
</div> |
|
</div> |
|
|
|
<a href="https://ameddes.com/onboarding/splash" class="cta-button">Open ClosetCoach App</a> |
|
</div> |
|
|
|
<!-- Tips Section --> |
|
<div class="tips-section"> |
|
<div class="tips-title">💡 Pro Tips to Engage Your New Subscriber</div> |
|
|
|
<div class="tip-item"> |
|
<div class="tip-icon">1</div> |
|
<div class="tip-text"> |
|
<strong>Start a conversation:</strong> Send them a direct message to introduce yourself and understand their style goals. |
|
</div> |
|
</div> |
|
|
|
<div class="tip-item"> |
|
<div class="tip-icon">2</div> |
|
<div class="tip-text"> |
|
<strong>Update your portfolio:</strong> Post fresh styling photos and outfit ideas that showcase your expertise and aesthetic. |
|
</div> |
|
</div> |
|
|
|
<div class="tip-item"> |
|
<div class="tip-icon">3</div> |
|
<div class="tip-text"> |
|
<strong>Offer personalized styling:</strong> Chat with them to understand their wardrobe and suggest pieces that match their style. |
|
</div> |
|
</div> |
|
|
|
<div class="tip-item"> |
|
<div class="tip-icon">4</div> |
|
<div class="tip-text"> |
|
<strong>Schedule video calls:</strong> Organize virtual styling sessions to provide more personalized guidance and build stronger connections. |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<!-- Footer --> |
|
<div class="footer"> |
|
<p class="footer-text"> |
|
Keep inspiring and building your style community!<br> |
|
Your expertise is making a difference in someone's fashion journey. |
|
</p> |
|
|
|
<p class="footer-text" style="margin-top: 24px;"> |
|
© 2025 ClosetCoach. All rights reserved. |
|
</p> |
|
</div> |
|
</div> |
|
</body> |
|
</html> |
|
""" |
|
|
|
return f""" |
|
<html> |
|
<body> |
|
<h1>Olá!</h1> |
|
<p>Este é um email automático do Streamify.</p> |
|
</body> |
|
</html> |
|
""" |
|
|
|
async def send_email_gmail(to_email: str, subject: str, body_html: str): |
|
access_token = get_access_token() |
|
|
|
msg = MIMEText(body_html, 'html', 'utf-8') |
|
msg['To'] = to_email |
|
msg['From'] = formataddr((SENDER_NAME, EMAIL_ADDRESS)) |
|
msg['Subject'] = subject |
|
|
|
raw_message = base64.urlsafe_b64encode(msg.as_bytes()).decode() |
|
|
|
url = "https://gmail.googleapis.com/gmail/v1/users/me/messages/send" |
|
headers = { |
|
"Authorization": f"Bearer {access_token}", |
|
"Content-Type": "application/json" |
|
} |
|
payload = {"raw": raw_message} |
|
|
|
async with aiohttp.ClientSession() as session: |
|
async with session.post(url, headers=headers, json=payload) as resp: |
|
response_text = await resp.text() |
|
if resp.status != 200: |
|
raise HTTPException(status_code=resp.status, detail=f"Gmail API error: {response_text}") |
|
|
|
@router.post("/send-email") |
|
async def send_email_route(email_req: EmailRequest): |
|
html_content = generate_email_html(email_req.type, email_req.to) |
|
await send_email_gmail(email_req.to, email_req.subject, html_content) |
|
return {"detail": "Email enviado com sucesso!"} |