Django使用SendGrid发送带zip附件邮件失败问题排查求助
问题排查与修复方案
1. 先修正附件大小校验逻辑
你当前打印的sys.getsizeof(zip_buffer)是BytesIO对象本身的内存占用,不是压缩包真实大小,完全无法作为参考。请替换为以下代码获取真实附件大小:
'size': f'{len(zip_buffer.getvalue())}'
SendGrid对单封邮件(含内容、所有附件)的总大小限制为30MB,超过限制的请求会被直接拦截,不会出现在发送列表中。如果你的附件超过该限制,请拆分压缩包后分批发送。
2. 排查非ASCII字符编码问题
你的邮件主题、正文、压缩包内的文件名都包含俄文等非ASCII字符,旧版本Django+SMTP后端处理非ASCII内容时可能出现MIME格式错误,导致SendGrid直接拒收请求:
- 显式指定邮件编码:在初始化
EmailMessage后添加msg.encoding = 'utf-8' - 先将压缩包内的文件名改为纯英文测试,如果可以发送,说明是压缩包内文件名编码问题,Python3.6的
zipfile打包非ASCII文件名默认使用CP437编码,和大多数系统兼容有问题,可以对文件名做URL编码后再写入压缩包。
3. 排除PDF生成与压缩包损坏问题
- 单独测试
generate_pdf_file函数在服务器环境的返回值,确认返回的是正常的PDF字节,不是空值或错误内容 - 可以在打包后临时把压缩包写入服务器本地磁盘,手动检查是否可以正常解压、里面的PDF是否可打开,排除压缩包损坏导致SendGrid拒收的问题
- 你当前初始化
ZipFile时关闭了Zip64支持,如果压缩包总大小超过2GB会触发报错,建议把第四个参数改为True开启Zip64支持:
with zipfile.ZipFile(zip_buffer, 'a', compression, True) as f:
4. 捕获发送环节的具体异常
你当前的全局异常捕获只返回了错误字符串,无法定位到send环节的具体报错。可以在msg.send前后加日志,打印SMTP返回的错误码和信息:
常见的错误类型:
SMTPDataError: 552:附件大小超过服务商限制SMTPDataError: 500:MIME格式错误,多为编码问题导致
5. 排除服务超时问题
如果批量生成PDF+打包的总耗时超过uwsgi/nginx的超时配置,进程会被直接杀死,发送逻辑根本不会执行。可以先减少UUID的数量,只生成1个小的PDF测试是否能发送成功,如果可以的话调整服务超时时间,或者把PDF生成、邮件发送逻辑改成异步任务处理,避免接口超时。
内容的提问来源于stack exchange,提问作者Ian
相关产品推荐
相关产品推荐

