"""
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 = "AniCove — Password Reset Code"
html_body = f"""\
AniCove
|
|
Your password reset code is:
|
|
{code}
|
|
This code expires in 5 minutes.
If you didn't request this, you can safely ignore this email.
|
|
"""
msg = MIMEMultipart("alternative")
msg["Subject"] = subject
msg["From"] = sender
msg["To"] = to_email
# Plain-text fallback
text_body = (
f"AniCove — 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