AI-News/backend/app/db/repositories/email_codes.py

69 lines
2.5 KiB
Python
Raw Normal View History

2025-12-04 10:04:21 +08:00
# app/services/mailer.py
import smtplib
import ssl
from email.message import EmailMessage
from typing import Optional
from loguru import logger
from app.core.config import get_app_settings
def _build_message(*, from_email: str, to_email: str, subject: str, html: str) -> EmailMessage:
msg = EmailMessage()
msg["From"] = from_email
msg["To"] = to_email
msg["Subject"] = subject
msg.set_content("Your email client does not support HTML.")
msg.add_alternative(html, subtype="html")
return msg
def send_email(to_email: str, subject: str, html: str) -> bool:
"""
同步发送成功返回 True失败返回 False并打印详细日志
- 端口 465使用 SMTP_SSL
- 其他端口使用 SMTP + (可选)STARTTLS
"""
s = get_app_settings()
from_email = str(s.mail_from)
smtp_host = s.smtp_host
smtp_port = int(s.smtp_port)
smtp_user: Optional[str] = s.smtp_user.get_secret_value() if s.smtp_user else None
smtp_pass: Optional[str] = s.smtp_password.get_secret_value() if s.smtp_password else None
msg = _build_message(from_email=from_email, to_email=to_email, subject=subject, html=html)
logger.info(
"SMTP send start → host={} port={} tls={} from={} to={}",
smtp_host, smtp_port, s.smtp_tls, from_email, to_email,
)
try:
if smtp_port == 465:
context = ssl.create_default_context()
with smtplib.SMTP_SSL(smtp_host, smtp_port, context=context, timeout=20) as server:
if smtp_user and smtp_pass:
server.login(smtp_user, smtp_pass)
server.send_message(msg)
else:
with smtplib.SMTP(smtp_host, smtp_port, timeout=20) as server:
server.ehlo()
if s.smtp_tls:
context = ssl.create_default_context()
server.starttls(context=context)
server.ehlo()
if smtp_user and smtp_pass:
server.login(smtp_user, smtp_pass)
server.send_message(msg)
logger.info("SMTP send OK to {}", to_email)
return True
except smtplib.SMTPResponseException as e:
# 能拿到服务端 code/resp 的错误
logger.error("SMTPResponseException: code={} msg={}", getattr(e, "smtp_code", None), getattr(e, "smtp_error", None))
return False
except Exception as e:
logger.exception("SMTP send failed: {}", e)
return False