55 lines
1.8 KiB
Python
55 lines
1.8 KiB
Python
"""
|
||
邮件发送模块。
|
||
|
||
通过 SMTP 发送验证码邮件,配置项从 .env 读取:
|
||
- SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_AUTH_CODE / EMAIL_FROM
|
||
163 邮箱:smtp.163.com,端口 465(SSL),密码处填写授权码。
|
||
"""
|
||
|
||
import os
|
||
import smtplib
|
||
from email.header import Header
|
||
from email.mime.text import MIMEText
|
||
from email.utils import formataddr
|
||
|
||
from dotenv import load_dotenv
|
||
|
||
from .database import PROJECT_ROOT
|
||
|
||
# 加载项目根目录下的 .env(重复调用无副作用)
|
||
load_dotenv(PROJECT_ROOT / ".env")
|
||
|
||
SMTP_HOST = os.getenv("SMTP_HOST", "smtp.163.com")
|
||
SMTP_PORT = int(os.getenv("SMTP_PORT") or "465")
|
||
SMTP_USER = os.getenv("SMTP_USER", "")
|
||
SMTP_AUTH_CODE = os.getenv("SMTP_AUTH_CODE", "")
|
||
EMAIL_FROM = os.getenv("EMAIL_FROM", SMTP_USER)
|
||
|
||
|
||
def send_verification_code(to_email: str, code: str) -> None:
|
||
"""向指定邮箱发送验证码邮件;发送失败时抛出异常由调用方处理。"""
|
||
if not SMTP_USER or not SMTP_AUTH_CODE:
|
||
raise RuntimeError("SMTP 未配置:请在 .env 中设置 SMTP_USER / SMTP_AUTH_CODE")
|
||
|
||
subject = "博客 - 邮箱验证码"
|
||
body = (
|
||
f"您好,\n\n"
|
||
f"您的验证码是:{code}\n"
|
||
f"验证码 10 分钟内有效,请勿泄露给他人。\n\n"
|
||
f"如非本人操作,请忽略本邮件。"
|
||
)
|
||
message = MIMEText(body, "plain", "utf-8")
|
||
message["Subject"] = Header(subject, "utf-8")
|
||
message["From"] = formataddr(("MyBlog", EMAIL_FROM))
|
||
message["To"] = to_email
|
||
|
||
if SMTP_PORT == 465:
|
||
server = smtplib.SMTP_SSL(SMTP_HOST, SMTP_PORT, timeout=15)
|
||
else:
|
||
server = smtplib.SMTP(SMTP_HOST, SMTP_PORT, timeout=15)
|
||
server.starttls()
|
||
try:
|
||
server.login(SMTP_USER, SMTP_AUTH_CODE)
|
||
server.sendmail(EMAIL_FROM, [to_email], message.as_string())
|
||
finally:
|
||
server.quit() |