107 lines
3.5 KiB
Python
Raw Permalink Normal View History

2025-02-13 02:27:44 +08:00
# _*_ coding : UTF-8 _*_
# @Time : 2025/01/26 21:51
# @UpdateTime : 2025/01/26 21:51
# @Author : sonder
# @File : mail.py
# @Software : PyCharm
# @Comment : 本程序
import random
from datetime import timedelta
from email.message import EmailMessage
from email.utils import formataddr
from aiosmtplib import send
from fastapi import Request
from jinja2 import Environment, FileSystemLoader
from config.constant import RedisKeyConfig
from config.env import AppConfig, EmailConfig
from utils.log import logger
class Email:
"""
邮件发送类用于发送邮件
"""
@classmethod
async def generate_verification_code(cls, length: int = 4) -> str:
"""
随机生成数字验证码
:param length: 验证码长度
:return:
"""
return ''.join(str(random.randint(0, 9)) for _ in range(length))
@classmethod
async def send_email(cls, request: Request, username: str, title: str = "注册", mail: str = "") -> bool:
"""
发送邮件
:param request: 请求对象
:param username: 用户账号
:param title: 邮件标题
:param mail: 邮箱地址
"""
code = await cls.generate_verification_code(4)
codeStr = ""
for i in code:
codeStr += f"""<button class="button">{i}</button>"""
env = Environment(loader=FileSystemLoader('templates'))
template = env.get_template('mail_en.html')
content = template.render(
TITLE=title,
CODE=codeStr,
PROJECTNAME=AppConfig.app_name,
)
subject = f"{AppConfig.app_name}-{title} Verification Code"
sendName = AppConfig.app_name
hostname = EmailConfig.email_host
port = EmailConfig.email_port
message = EmailMessage()
message["From"] = formataddr((sendName, EmailConfig.email_username))
message["To"] = mail
message["Subject"] = subject
message.set_content(content, subtype="html")
try:
await send(
message,
hostname=hostname,
port=port,
username=EmailConfig.email_username,
password=EmailConfig.email_password
)
await request.app.state.redis.set(f"{RedisKeyConfig.EMAIL_CODES.key}:{mail}-{username}", code,
ex=timedelta(minutes=2))
logger.info(f"发送邮件至{mail}成功,验证码:{code}")
return True
except Exception as e:
logger.error(e)
return False
@classmethod
async def verify_code(cls, request: Request, username: str, mail: str, code: str) -> dict:
"""
验证验证码
:param request: 请求对象
:param username: 用户账号
:param mail: 邮箱地址
:param code: 验证码
"""
redis_code = await request.app.state.redis.get(f"{RedisKeyConfig.EMAIL_CODES.key}:{mail}-{username}")
if redis_code is None:
return {
"status": False,
"msg": "验证码已过期"
}
if str(redis_code).lower() == code.lower():
await request.app.state.redis.delete(f"{RedisKeyConfig.EMAIL_CODES.key}:{mail}-{username}")
return {
"status": True,
"msg": "验证码正确"
}
return {
"status": False,
"msg": "验证码错误"
}