使用FastAPI-Mail发送多邮箱时触发邮箱格式无效错误
使用fastapi-mail多邮箱发送报错:not a valid email address
问题详情
用fastapi-mail实现多邮箱多文件发送,单邮箱发送正常,但把邮箱参数改为List[EmailStr]后,触发not a valid email address错误。
错误信息
not a valid email address
相关代码
from fastapi import FastAPI, BackgroundTasks, Form, File, UploadFile from fastapi.responses import JSONResponse from pydantic import EmailStr from fastapi_mail import MessageSchema, FastMail, ConnectionConfig from typing import List, Optional # 假设res是读取配置的函数 def res(key): # 示例配置,实际替换为你的配置读取逻辑 config = { "MAIL_USERNAME": "your_username", "MAIL_PASSWORD": "your_password", "MAIL_PORT": 587, "MAIL_SERVER": "smtp.example.com", "MAIL_TLS": True, "MAIL_SSL": False, "USE_CREDENTIALS": True, "VALIDATE_CERTS": True } return config.get(key) app = FastAPI() @app.post("/file") async def send_file( background_tasks: BackgroundTasks, email: List[EmailStr] = Form(...), # 此处从单个EmailStr改为List[EmailStr] file: Optional[List[UploadFile]] = File(...), ) -> JSONResponse: print(email) print(file) message = MessageSchema( subject="Fastapi mail module", recipients=email, body="Simple background task", subtype="html", attachments=file ) fm = FastMail(ConnectionConfig( MAIL_USERNAME=res("MAIL_USERNAME"), MAIL_PASSWORD=res("MAIL_PASSWORD"), MAIL_FROM="admin@acsebs.com", MAIL_PORT=res("MAIL_PORT"), MAIL_SERVER=res("MAIL_SERVER"), MAIL_FROM_NAME="send attachment email service", MAIL_TLS=res("MAIL_TLS"), MAIL_SSL=res("MAIL_SSL"), USE_CREDENTIALS=res("USE_CREDENTIALS"), VALIDATE_CERTS=res("VALIDATE_CERTS") )) background_tasks.add_task(fm.send_message, message) return JSONResponse(status_code=200, content={"message": "email has been sent"})
提交与错误截图
- Swagger UI提交数据界面:

- 错误提示界面:

解决方案
原因分析
FastAPI中List[EmailStr] = Form(...)期望前端提交多个同名的email参数(比如email=a@test.com&email=b@test.com),但你在Swagger UI的单个输入框里用逗号分隔多个邮箱,会被解析成一个字符串,无法通过EmailStr的格式验证,从而报错。
两种解决方式
方式1:保留List[EmailStr]参数,正确提交
在Swagger UI中,点击email字段旁的Add string按钮,添加多个输入框,每个输入框填写一个单独的邮箱地址,再提交即可。这种方式符合FastAPI对表单List参数的解析规则,无需修改代码。
方式2:支持逗号分隔的邮箱输入
如果希望用户在单个输入框用逗号分隔多个邮箱,需要修改代码手动处理:
- 将邮箱参数改为
str类型 - 分割字符串并逐个验证邮箱格式
修改后的核心代码:
from pydantic import validate_email, ValidationError @app.post("/file") async def send_file( background_tasks: BackgroundTasks, email: str = Form(...), # 改为str类型 file: Optional[List[UploadFile]] = File(...), ) -> JSONResponse: try: # 分割并去除空白字符 email_list = [e.strip() for e in email.split(",") if e.strip()] # 逐个验证邮箱格式 for e in email_list: validate_email(e) except ValidationError: return JSONResponse(status_code=400, content={"message": "无效的邮箱地址"}) # 后续逻辑不变 message = MessageSchema( subject="Fastapi mail module", recipients=email_list, body="Simple background task", subtype="html", attachments=file ) fm = FastMail(ConnectionConfig(...)) # 配置部分不变 background_tasks.add_task(fm.send_message, message) return JSONResponse(status_code=200, content={"message": "email has been sent"})
额外验证
确认fastapi-mail的MessageSchema的recipients参数支持List[str]或List[EmailStr](从官方文档来看是支持的,因为单邮箱场景下EmailStr可以正常传入)。
内容的提问来源于stack exchange,提问作者samuel.situmorang
相关产品推荐
相关产品推荐

