anicove2 / api /utils /mailer.py
mwask's picture
Upload 124 files
19ecc0d verified
Raw
History Blame Contribute Delete
3.89 kB
"""
Email utility for sending password reset codes via Gmail SMTP.
"""
import smtplib
import ssl
import logging
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from ..core.config import Config
logger = logging.getLogger(__name__)
SMTP_SERVER = "smtp.gmail.com"
SMTP_PORT = 465
def send_reset_code_email(to_email: str, code: str) -> bool:
"""
Send a password reset code email via Gmail SMTP.
Args:
to_email: Recipient email address.
code: The 6-digit reset code (plaintext, for display in email).
Returns:
True if sent successfully, False otherwise.
"""
sender = Config.GMAIL_USER
password = Config.GMAIL_APP_PASSWORD
if not sender or not password:
logger.error("Gmail credentials not configured. Set GMAIL_USER and GMAIL_APP_PASSWORD.")
return False
subject = "YumeZone — Password Reset Code"
html_body = f"""\
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body style="margin:0;padding:0;background:#0a0a0a;font-family:'Inter',Arial,sans-serif;">
<table width="100%" cellpadding="0" cellspacing="0" style="background:#0a0a0a;padding:40px 0;">
<tr>
<td align="center">
<table width="420" cellpadding="0" cellspacing="0"
style="background:#141414;border-radius:16px;border:1px solid #222;padding:40px;">
<tr>
<td align="center" style="padding-bottom:24px;">
<h1 style="margin:0;color:#fff;font-size:22px;font-weight:700;">YumeZone</h1>
</td>
</tr>
<tr>
<td align="center" style="padding-bottom:8px;">
<p style="margin:0;color:#999;font-size:14px;">Your password reset code is:</p>
</td>
</tr>
<tr>
<td align="center" style="padding:20px 0;">
<div style="display:inline-block;background:#1a1a2e;border:2px solid #6c5ce7;
border-radius:12px;padding:16px 36px;letter-spacing:12px;
font-size:32px;font-weight:700;color:#a29bfe;font-family:monospace;">
{code}
</div>
</td>
</tr>
<tr>
<td align="center" style="padding-top:16px;">
<p style="margin:0;color:#666;font-size:13px;">
This code expires in <strong style="color:#e17055;">5 minutes</strong>.
</p>
<p style="margin:8px 0 0;color:#555;font-size:12px;">
If you didn't request this, you can safely ignore this email.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>"""
msg = MIMEMultipart("alternative")
msg["Subject"] = subject
msg["From"] = sender
msg["To"] = to_email
# Plain-text fallback
text_body = (
f"YumeZone — Password Reset\n\n"
f"Your reset code is: {code}\n\n"
f"This code expires in 5 minutes.\n"
f"If you didn't request this, ignore this email."
)
msg.attach(MIMEText(text_body, "plain"))
msg.attach(MIMEText(html_body, "html"))
try:
context = ssl.create_default_context()
with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT, context=context) as server:
server.login(sender, password)
server.sendmail(sender, to_email, msg.as_string())
logger.info(f"Reset code email sent to {to_email}")
return True
except smtplib.SMTPAuthenticationError:
logger.error("Gmail SMTP authentication failed. Check GMAIL_USER / GMAIL_APP_PASSWORD.")
return False
except Exception as e:
logger.error(f"Failed to send reset code email to {to_email}: {e}")
return False