React表单提交后无法收到Django邮件通知(数据可正常入库)
表单提交数据入库但邮件通知时断时续的排查与解决
核心问题分析
数据能正常存入数据库,但邮件通知仅在控制台测试、修改路由后首次提交时生效,后续提交失效——说明邮件基础配置(SMTP参数、账号权限)无问题,故障出在请求路由匹配、同步执行逻辑或异常捕获环节。
排查与解决方案
1. 确认请求路由的唯一性
你代码中存在两个处理POST请求的视图:formApi(仅存数据不发邮件)和form_submission_view(存数据+发邮件)。如果前端请求地址存在缓存、路由配置冲突,会导致部分请求命中无邮件逻辑的formApi,出现“时好时坏”的现象:
- 检查React前端的API调用地址,确保始终指向
form_submission_view对应的路由; - 清理浏览器缓存,避免旧请求地址残留;
- 查看Django路由配置,确保两个视图的路径无重叠或优先级冲突。
2. 改用异步任务处理邮件发送
同步执行send_mail会占用请求线程,若SMTP连接未正确释放、遭遇超时,会导致后续请求无法建立新连接发送邮件:
- 使用
asyncio将邮件发送转为异步任务(无需额外依赖),示例代码如下:
import asyncio import logging logger = logging.getLogger(__name__) async def send_async_email(name, email, subject, message): try: send_mail( 'New Form Submission', f'You have a new form submission:\n\nName: {name}\nEmail: {email}\nSubject: {subject}\nMessage: {message}', settings.EMAIL_HOST_USER, [settings.EMAIL_HOST_USER], fail_silently=False, ) logger.info(f"邮件发送成功:来自{email}的表单提交") except Exception as e: logger.error(f"邮件发送失败:{str(e)}", exc_info=True) # 在form_submission_view中替换原send_mail代码 asyncio.create_task(send_async_email(name, email, subject, message))
3. 细化异常日志捕获
当前视图的异常捕获过于宽泛,无法定位邮件发送的具体错误(如SMTP连接重置、账号频率限制):
- 添加日志模块,记录详细错误信息:
import logging logger = logging.getLogger(__name__) # 替换原异常捕获块 except json.JSONDecodeError: logger.error("表单提交接收无效JSON数据") return JsonResponse({'error': '无效的JSON格式'}, status=400) except Exception as e: logger.error(f"表单处理异常:{str(e)}", exc_info=True) return JsonResponse({'error': '服务器内部错误'}, status=500)
- 查看Django日志文件,可直接获取邮件发送失败的具体原因(如Gmail的频率限制、SMTP认证问题)。
4. 检查SMTP服务限制
以Gmail为例,短时间内多次发送邮件会触发频率限制,导致后续邮件被拦截:
- 若使用Gmail,确认已开启“低安全性应用访问”(未开启2FA时)或使用App密码(开启2FA时);
- 测试更换其他SMTP服务商(如网易邮箱),排除平台限制问题。
优化后的完整视图示例
from django.core.mail import send_mail from django.conf import settings from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from .models import Form import json import logging import asyncio logger = logging.getLogger(__name__) async def send_async_submission_email(name, email, subject, message): try: send_mail( 'New Form Submission', f'You have a new form submission:\n\nName: {name}\nEmail: {email}\nSubject: {subject}\nMessage: {message}', settings.EMAIL_HOST_USER, [settings.EMAIL_HOST_USER], fail_silently=False, ) logger.info(f"邮件发送成功:来自{email}的表单提交") except Exception as e: logger.error(f"邮件发送失败:{str(e)}", exc_info=True) @csrf_exempt def form_submission_view(request): if request.method == 'POST': try: data = json.loads(request.body) name = data.get('name') email = data.get('email') subject = data.get('subject') message = data.get('message') # 表单字段校验 if not name: return JsonResponse({'error': '请填写姓名'}, status=400) if not email: return JsonResponse({'error': '请填写邮箱'}, status=400) if not subject: return JsonResponse({'error': '请填写主题'}, status=400) if not message: return JsonResponse({'error': '请填写留言内容'}, status=400) # 保存数据到数据库 Form.objects.create(name=name, email=email, subject=subject, message=message) logger.info(f"表单数据保存成功:来自{email}的提交") # 异步发送邮件 asyncio.create_task(send_async_submission_email(name, email, subject, message)) return JsonResponse({'message': '表单提交成功!'}) except json.JSONDecodeError: logger.error("表单提交接收无效JSON数据") return JsonResponse({'error': '无效的请求格式'}, status=400) except Exception as e: logger.error(f"表单处理异常:{str(e)}", exc_info=True) return JsonResponse({'error': '服务器内部错误'}, status=500) else: return JsonResponse({'error': '不支持的请求方法'}, status=405)
内容的提问来源于stack exchange,提问作者Saiyad Aamir
相关产品推荐
相关产品推荐

