57 lines
1.6 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 app.core.config import get_app_settings
def send_email(to_email: str, subject: str, html: str) -> None:
"""
发送邮件
- 端口为 465 时使用 SSL 直连SMTP_SSL
- 其他端口按配置 smtp_tls 决定是否 STARTTLS
"""
s = get_app_settings()
host = s.smtp_host
port = int(s.smtp_port)
use_starttls = bool(s.smtp_tls)
# SecretStr / Optional 兼容处理
smtp_user = s.smtp_user.get_secret_value() if getattr(s, "smtp_user", None) else None
smtp_pass = s.smtp_password.get_secret_value() if getattr(s, "smtp_password", None) else None
msg = EmailMessage()
msg["From"] = str(s.mail_from) # EmailStr -> str
msg["To"] = to_email
msg["Subject"] = subject
# 纯文本 + HTML多部件
msg.set_content("Your mail client does not support HTML.")
msg.add_alternative(html, subtype="html")
ctx = ssl.create_default_context()
# === 建立连接 ===
if port == 465:
server = smtplib.SMTP_SSL(host, port, context=ctx, timeout=20)
else:
server = smtplib.SMTP(host, port, timeout=20)
server.ehlo()
if use_starttls:
server.starttls(context=ctx)
server.ehlo()
try:
# 如配置了用户名/密码,则登录
if smtp_user and smtp_pass:
server.login(smtp_user, smtp_pass)
server.send_message(msg)
finally:
try:
server.quit()
except Exception:
# 连接已断开也无妨,忽略
pass