smtplib发送长邮件触发ascii编码UnicodeEncodeError报错求助
问题原因
这个报错和正文长度没有直接关系,你观察到的「超过长度阈值就触发」只是巧合:
- 报错信息里的
\u2019是Unicode右弯单引号(排版用的’,不是ASCII范围内的直单引号'),不在ASCII码0-127的覆盖范围内。 smtplib.SMTP.sendmail()接收字符串类型的邮件内容时,默认会用ASCII编码做序列化,只要内容里出现任何非ASCII字符,就会抛出这个编码错误。- 你误以为正文全是大小写字母和数字,实际是复制内容时(比如从Word、网页粘贴)不小心混入了这个弯引号。短文本测试时你删掉了包含这个字符的段落,所以能正常运行;正文拉长后刚好把这个字符包含进去,就触发了报错,不存在所谓的长度阈值。
- 直接修改smtplib.py系统库文件是完全错误的做法,很容易破坏库本身的逻辑,直接导致脚本无法运行。
另外你当前手拼邮件的写法不符合SMTP协议规范:邮件头(比如Subject)和正文之间必须留一个空行分隔,你现在的写法邮件客户端会把正文也识别为邮件头,大概率显示异常。
修复方案
不要修改系统/第三方库源码,以下两种合规方案选一种即可:
方案1:最小改动适配现有代码
给邮件添加编码声明头,同时把正文转成UTF-8编码的字节串再传入sendmail:
import smtplib import sys smtpObj = smtplib.SMTP('smtp endpoint', 587) smtpObj.ehlo() smtpObj.starttls() smtpObj.login('login', sys.argv[1]) for name, email in unmessagedmembers.items(): # 注意头部和正文之间空一行,添加Content-Type声明UTF-8编码 body = """Content-Type: text/plain; charset=utf-8 Subject: Research a {} lot of text more text""".format(name) # 将字符串编码为utf-8字节串再传入sendmail body_bytes = body.encode('utf-8') print('Sending email to {}...'.format(email)) sendmailStatus = smtpObj.sendmail('me@email.com', email, body_bytes) if sendmailStatus != {}: print('There was a problem sending email to {}: {}'.format(email, sendmailStatus)) smtpObj.quit()
方案2:用标准库构造合规邮件(推荐)
Python官方推荐用email模块构造MIME邮件,自动处理编码、头格式等协议细节,不容易出兼容问题:
import smtplib import sys from email.mime.text import MIMEText smtpObj = smtplib.SMTP('smtp endpoint', 587) smtpObj.ehlo() smtpObj.starttls() smtpObj.login('login', sys.argv[1]) for name, email in unmessagedmembers.items(): # 构造纯文本邮件,指定utf-8编码 msg = MIMEText("a {} lot of text\nmore text".format(name), 'plain', 'utf-8') msg['Subject'] = 'Research' msg['From'] = 'me@email.com' msg['To'] = email print('Sending email to {}...'.format(email)) sendmailStatus = smtpObj.send_message(msg) if sendmailStatus != {}: print('There was a problem sending email to {}: {}'.format(email, sendmailStatus)) smtpObj.quit()
额外排查点
如果改完仍报同类编码错误,检查name字段(尤其是从外部文件、网页爬取的姓名数据)、邮件地址里有没有混入非ASCII的特殊排版字符。
内容的提问来源于stack exchange,提问作者user15267842
相关产品推荐
相关产品推荐

