You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用FastAPI-Mail后台任务发送用户注册验证邮件无反应且无报错问题求助

注册路由完成后验证邮件未发送且无报错排查

我正在开发一个FastAPI的用户注册路由,预期完成用户注册后自动向注册邮箱发送验证邮件,但目前邮件并未发送,且控制台没有任何报错信息。以下是我的相关代码,麻烦帮忙排查下问题所在:

注册路由代码

@router.post('/register')
async def register_user(data: MakeUser, background_task: BackgroundTasks, request: Request, db: Session = Depends(get_db)):
    try:
        # NOTE: It is better to go with this right now in future avoid making multiple querys
        if user_crud.validate_email(data.email, db):
            return JSONResponse("Email Already Exist", status.HTTP_406_NOT_ACCEPTABLE)
        if user_crud.validate_username(data.username, db):
            return JSONResponse(
                "Username is taken", status_code=status.HTTP_406_NOT_ACCEPTABLE)
        data = user_crud.create_user(data, db)
        email_verification_token = create_token_for_email_verification(
            {"user_id": data.public_id, "email": data.email})
        email_verification_url = f'{request.base_url}auth/verify/{email_verification_token}'
        await send_email_verification_mail(
            background_task, "Email Verification", data.email, {"url": email_verification_url})
        return data
    except Exception as e:
        print(e)
        return HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Problem creating user")

邮件发送脚本

async def send_email_verification_mail(background_task: BackgroundTasks, subject: str, email_to: str, body):
    print(os.environ.get("MAIL_USERNAME"))
    message = MessageSchema(
        subject=subject,
        recipients=[email_to],
        body=body
    )
    fm = FastMail(configs)
    print("Sendig Mail")
    background_task.add_task(fm.send_message, message)
    print("Mail Sent")

我帮你梳理几个可能的问题点,你可以逐一排查:

  • 背景任务未执行:FastAPI的BackgroundTasks是在请求返回给客户端之后才会运行的。如果你的应用在请求结束后就终止了(比如本地开发用uvicorn --reload时,代码热重载导致进程重启,或者测试时请求完成后直接关闭了服务),那背景任务根本没机会执行。你可以先临时去掉背景任务,直接在路由里调用await fm.send_message(message),看看邮件能不能正常发送,先排除背景任务的影响。

  • 邮件配置不完整/错误:你打印了MAIL_USERNAME,但要确认所有邮件相关的环境变量(比如MAIL_PASSWORD、MAIL_SERVER、MAIL_PORT、MAIL_STARTTLS/MAIL_SSL)都配置正确。不同邮箱服务商的要求不一样,比如Gmail需要启用应用专用密码,QQ邮箱需要开启POP3/SMTP服务。你可以写个简单的测试脚本,直接用SMTP库验证配置是否能正常发送邮件:

    import os
    import smtplib
    from email.mime.text import MIMEText
    
    def test_smtp_config():
        msg = MIMEText("这是一封测试邮件")
        msg["Subject"] = "邮件配置测试"
        msg["From"] = os.environ.get("MAIL_USERNAME")
        msg["To"] = "你的测试邮箱地址"
    
        try:
            with smtplib.SMTP(os.environ.get("MAIL_SERVER"), int(os.environ.get("MAIL_PORT"))) as server:
                if os.environ.get("MAIL_STARTTLS") == "True":
                    server.starttls()
                server.login(os.environ.get("MAIL_USERNAME"), os.environ.get("MAIL_PASSWORD"))
                server.send_message(msg)
            print("测试邮件发送成功!")
        except Exception as e:
            print(f"发送失败,错误信息:{e}")
    
    test_smtp_config()
    
  • MessageSchema参数错误:FastMail的MessageSchema如果要发送HTML邮件,应该使用html参数而不是body(body一般对应纯文本内容)。你传入的body是一个字典{"url": email_verification_url},这显然不是合法的邮件内容。你需要先把这个字典渲染成HTML或纯文本模板,比如用Jinja2:

    # 先定义模板
    from jinja2 import Template
    
    verification_template = Template("请点击链接验证邮箱:<a href='{{ url }}'>{{ url }}</a>")
    html_content = verification_template.render(body)
    
    message = MessageSchema(
        subject=subject,
        recipients=[email_to],
        html=html_content  # 用html参数代替body
    )
    
  • 背景任务中的异常未被捕获:fm.send_message如果执行出错,因为是在背景任务里运行,异常不会被路由里的try-except捕获,所以你看不到报错。可以给背景任务的任务函数加上异常处理,或者临时直接调用await fm.send_message(message),看看有没有报错信息。

内容的提问来源于stack exchange,提问作者Tazim Rahbar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 20:24:07