Files
FastapiAdmin/backend/app/utils/email_util.py
T
zhangtao 73f2823692 refactor: 大规模代码整理与功能优化
1. 重构后端API路由、CRUD与模块结构,整合日志管理,移除废弃demo代码
2. 优化前端组件类型定义、样式与路由配置,修复权限判断逻辑
3. 调整默认排序规则、滚动条样式与工具类函数,更新依赖与配置文件
4. 修复多处类型不匹配与默认值问题,完善表单与菜单验证逻辑
2026-06-17 01:56:31 +08:00

89 lines
2.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
email_util.py — 邮件发送工具
职责:
- 渲染 Jinja2 模板
- 通过 fastapi-mail 发送邮件
使用方:EmailService.send_email_service()
"""
from typing import Any
from fastapi_mail import ConnectionConfig, FastMail, MessageSchema, MessageType
from jinja2 import Environment, StrictUndefined
def render_template(template_str: str, variables: dict[str, Any]) -> str:
"""
使用 Jinja2 渲染邮件模板。
参数:
- template_str: Jinja2 模板字符串
- variables: 变量字典
返回:渲染后的字符串
异常:TemplateError — 模板语法错误或变量缺失
"""
env = Environment(undefined=StrictUndefined, autoescape=True)
tmpl = env.from_string(template_str)
return tmpl.render(**variables)
async def send_email(
*,
smtp_host: str,
smtp_port: int,
smtp_user: str,
smtp_password: str,
use_tls: bool,
from_name: str,
to_email: str,
to_name: str | None,
subject: str,
body_html: str,
body_text: str | None = None,
timeout: int = 30,
) -> None:
"""
异步发送邮件(通过 fastapi-mail)。
参数均为关键字参数。
异常:
- SMTPException — SMTP 协议错误
- TimeoutError — 连接/发送超时
"""
# 构建 fastapi-mail 连接配置
# 端口 465 = 隐式 SSL,端口 587 = STARTTLS
is_ssl = smtp_port == 465
conf = ConnectionConfig(
MAIL_USERNAME=smtp_user,
MAIL_PASSWORD=smtp_password,
MAIL_FROM=smtp_user,
MAIL_FROM_NAME=from_name,
MAIL_SERVER=smtp_host,
MAIL_PORT=smtp_port,
MAIL_STARTTLS=not is_ssl and use_tls,
MAIL_SSL_TLS=is_ssl,
USE_CREDENTIALS=True,
VALIDATE_CERTS=False,
MAIL_TIMEOUT=timeout,
)
# 收件人格式:支持 "姓名 <邮箱>"(若有 to_name
recipient = f"{to_name} <{to_email}>" if to_name else to_email
# 构建邮件消息
message = MessageSchema(
subject=subject,
recipients=[recipient],
body=body_html,
subtype=MessageType.html,
)
fm = FastMail(conf)
await fm.send_message(message)