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()
|