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

Flask-Mail初始化报错:__init__()仅接受1个位置参数但传入2个

Flask-Mail初始化Message报错:TypeError: init() takes 1 positional argument but 2 were given

问题背景

开发基于FastAPI挂载Flask的网站,实现邮件确认路由时触发上述错误,且单独使用Flask也会出现该问题。

相关代码

app.init.py

from flask import Flask
from flask_bootstrap import Bootstrap
from app.config import DevelopmentConfig
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from fastapi import FastAPI, Request
from fastapi.middleware.wsgi import WSGIMiddleware
from flask_migrate import Migrate

app = FastAPI()

flask_app = Flask(__name__)

app.mount("/", WSGIMiddleware(flask_app))

运行文件

from app import app
import uvicorn

if __name__ == "__main__":
    uvicorn.run(app)

视图文件(views.py)

from app import flask_app
from flask import render_template, request, redirect, url_for, abort, flash
from itsdangerous import URLSafeTimedSerializer, TimestampSigner
from flask_mail import Mail, Message

mail = Mail()
mail.init_app(flask_app)
serializer = URLSafeTimedSerializer(flask_app.config["SECRET_KEY"])
timestamp = TimestampSigner(flask_app.config["SECRET_KEY"])

@flask_app.route("/confirm", methods=["POST", "GET"])
@login_required
def confirm():
    image = get_photo("cafe")
    user_email = current_user.email
    message = "请点击下方链接确认你的邮箱地址"
    token = serializer.dumps(user_email, salt="email-confirm")
    unsubscribe_token = serializer.dumps(user_email, salt="unsubscribe")
    link = url_for("confirm_email", token=token, _external=True)
    unsubscribe = url_for("unsubscribe", token=unsubscribe_token, _external=True)
    site_mail = flask_app.config["MAIL_USERNAME"]
    print(site_mail)
    msg = Message("Confirm Email", sender=site_mail, recipients=user_email)

    msg.body = render_template("public/email/single-news.html",
                               user=current_user,
                               link=link,
                               image=image,
                               message=message,
                               unsubscribe=unsubscribe)

    msg.html = render_template("public/email/single-news.html",
                               user=current_user,
                               link=link,
                               image=image,
                               message=message,
                               unsubscribe=unsubscribe)

    mail.send(msg)

    return redirect(url_for("index"))

Flask配置文件

class Config:
    DEBUG = True
    TESTING = False
    SESSION_COOKIE_SECURE = True
    SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:tool789@localhost/city"
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    JSON_AS_ASCII = True
    JSON_SORT_KEYS = True
    IJSONFY_MIMETYPE = 'application/json'
    SECRET_KEY = "b'\xf1L\xdb5D\x96M\xe5\xd1\x9f\x16+\xf4%A\x1e\xb9\xafm\xb8g\x1ct\x0e'"
    MAIL_SERVER = "smtp.gmail.com"
    MAIL_USERNAME = "myemail"
    MAIL_PASSWORD = "password"
    MAIL_PORT = 465
    MAIL_DEBUG = False
    MAIL_USE_SSL = True
    MAIL_USE_TSL = False

错误信息

FastAPI搭配Flask时的报错

INFO:     127.0.0.1:60517 - "GET /confirm HTTP/1.1" 500 Internal Server Error
ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 429, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 78, in __call__
    return await self.app(scope, receive, send)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\fastapi\applications.py", line 276, in __call__
    await super().__call__(scope, receive, send)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\starlette\applications.py", line 122, in __call__
    await self.middleware_stack(scope, receive, send)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\starlette\middleware\errors.py", line 184, in __call__
    raise exc
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\starlette\middleware\errors.py", line 162, in __call__
    await self.app(scope, receive, _send)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\starlette\middleware\exceptions.py", line 79, in __call__
    raise exc
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\starlette\middleware\exceptions.py", line 68, in __call__
    await self.app(scope, receive, sender)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 21, in __call__
    raise e
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 18, in __call__
    await self.app(scope, receive, send)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\starlette\routing.py", line 718, in __call__
    await route.handle(scope, receive, send)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\starlette\routing.py", line 443, in handle
    await self.app(scope, receive, send)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\starlette\middleware\wsgi.py", line 71, in __call__
    await responder(receive, send)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\starlette\middleware\wsgi.py", line 98, in __call__
    await anyio.to_thread.run_sync(self.wsgi, environ, self.start_response)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\anyio\to_thread.py", line 31, in run_sync
    return await get_asynclib().run_sync_in_worker_thread(
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\anyio\_backends\_asyncio.py", line 937, in run_sync_in_worker_thread
    return await future
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\anyio\_backends\_asyncio.py", line 867, in run
    result = context.run(func, *args)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\starlette\middleware\wsgi.py", line 132, in wsgi
    for chunk in self.app(environ, start_response):
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\flask\app.py", line 2551, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\flask\app.py", line 2531, in wsgi_app
    response = self.handle_exception(e)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\flask\app.py", line 2528, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\flask\app.py", line 1825, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\flask\app.py", line 1823, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\flask\app.py", line 1799, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\flask_login\utils.py", line 290, in decorated_view
    return current_app.ensure_sync(func)(*args, **kwargs)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\app\views.py", line 260, in confirm
    msg = Message("Confirm Email", sender=site_mail, recipients=user_email)
TypeError: __init__() takes 1 positional argument but 2 were given

单独使用Flask时的报错

127.0.0.1 - - [09/Apr/2023 18:21:09] "GET /confirm HTTP/1.1" 500 -
Traceback (most recent call last):
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\flask\app.py", line 2551, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\flask\app.py", line 2531, in wsgi_app
    response = self.handle_exception(e)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\flask\app.py", line 2528, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\flask\app.py", line 1825, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\flask\app.py", line 1823, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\flask\app.py", line 1799, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\venv\lib\site-packages\flask_login\utils.py", line 290, in decorated_view
    return current_app.ensure_sync(func)(*args, **kwargs)
  File "C:\Users\Pourya\PycharmProjects\favoritecafe\app\views.py", line 258, in confirm
    msg = Message("Confirm", sender=site_mail, recipients=user_email)
TypeError: __init__() takes 1 positional argument but 2 were given

解决方案

核心原因

  1. Flask-Mail版本差异:新版Flask-Mail(如3.x系列)重构了Message类,构造函数不再支持位置参数传邮件标题,必须用subject关键字参数指定;旧版虽支持位置参数,但recipients要求传入列表而非单个字符串。
  2. 参数格式错误:recipients参数需传入列表类型,直接传单个邮箱字符串会导致参数解析异常。

修复步骤

  1. 调整Message初始化代码
    将原代码:
msg = Message("Confirm Email", sender=site_mail, recipients=user_email)

修改为对应版本的写法:

  • 若使用新版Flask-Mail(3.x+):
msg = Message(subject="Confirm Email", sender=site_mail, recipients=[user_email])
  • 若使用旧版Flask-Mail(0.9.1及以下):
msg = Message("Confirm Email", sender=site_mail, recipients=[user_email])

重点:无论版本,recipients必须用列表包裹,即使只有一个收件人。

  1. 确认Flask-Mail版本
    执行命令查看当前版本:
pip show flask-mail

根据版本选择对应的初始化方式,避免版本不兼容问题。

  1. 加载Flask配置
    在app.__init__.py中添加配置加载代码,否则邮件配置不会生效:
# 假设你使用的是Config类
from app.config import Config
flask_app.config.from_object(Config)

内容的提问来源于stack exchange,提问作者Pourya Mohamadi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 19:14:54