Django3中名称超75字符的邮件因sanitize_address发送失败如何解决
Django 3 发送名称超过75字符邮件的解决方案
问题核心
Django 3版本中django/core/mail/message.py下的sanitize_address()方法存在已知缺陷:地址名称部分通过email.header.Header.encode()方法编码时,会默认在字符数达到75时自动插入换行符,导致邮件地址格式异常,最终无法成功发送邮件。
可落地实现方案
方案一:猴子补丁全局替换(改动最小,生效最快)
直接在项目启动时替换Django原生的sanitize_address方法,修改Header的最大行长度限制,避免自动换行:
- 在项目根目录下新建
patches/email_patch.py文件,写入以下代码:
from django.core.mail import message from email.header import Header def patched_sanitize_address(addr, encoding): if isinstance(addr, str): return addr name, addr_val = addr if not name: return addr_val # 调整最大行长度为1000,覆盖默认75字符的换行限制 name_encoded = Header(name, encoding, maxlinelen=1000).encode() return f"{name_encoded} <{addr_val}>" # 覆盖原生方法 message.sanitize_address = patched_sanitize_address
- 在项目根目录的
__init__.py中导入补丁,确保项目启动时自动加载:
from patches.email_patch import patched_sanitize_address
- 方案优势:无需修改原有业务邮件发送代码,全量兼容现有逻辑,适合需要快速修复的场景。
方案二:自定义SMTP邮件后端(无侵入,更安全)
如果不想全局修改Django底层方法,可以自定义邮件后端,单独处理地址格式化逻辑:
- 在项目下新建
backends/custom_email_backend.py文件,写入以下代码:
from django.core.mail.backends.smtp import EmailBackend from email.headerregistry import Address class LongAddressEmailBackend(EmailBackend): def format_single_address(self, addr_pair): name, email_addr = addr_pair if not name: return email_addr # 使用Python 3原生的Address类处理,不存在自动换行问题 return str(Address(display_name=name, addr_spec=email_addr)) def _send(self, email_message): # 格式化所有邮件地址字段 if isinstance(email_message.from_email, (list, tuple)): email_message.from_email = self.format_single_address(email_message.from_email) email_message.to = [self.format_single_address(addr) if isinstance(addr, (list, tuple)) else addr for addr in email_message.to] email_message.cc = [self.format_single_address(addr) if isinstance(addr, (list, tuple)) else addr for addr in email_message.cc] email_message.bcc = [self.format_single_address(addr) if isinstance(addr, (list, tuple)) else addr for addr in email_message.bcc] email_message.reply_to = [self.format_single_address(addr) if isinstance(addr, (list, tuple)) else addr for addr in email_message.reply_to] return super()._send(email_message)
- 在
settings.py中修改邮件后端配置:
EMAIL_BACKEND = 'backends.custom_email_backend.LongAddressEmailBackend'
- 方案优势:不会修改Django全局方法,升级Django版本时无兼容风险,适合对代码规范性要求较高的场景。
方案三:升级Django版本(长期最优解)
该问题已经在Django 3.2.10及更高的3.2系列版本、以及所有4.x版本中修复,如果业务允许升级框架版本,直接升级到对应版本即可彻底解决问题,无需额外代码修改。
内容的提问来源于stack exchange,提问作者Nicolás Gustavo Bruna
相关产品推荐
相关产品推荐

