Django: 包含Unicode字符的CSV邮件附件出现多余换行符
我在网站上有一个报告功能,可以通过电子邮件发送带有CSV文件的附件。最近我发现,如果其中一个字符串包含重音字符,我的CSV附件就会多出额外的换行。奇怪的是,如果字符串没有重音字符,我就看不到这些额外的换行。
代码大概是这样的:
# -*- coding: utf8 -*-
import unicodecsv
from StringIO import StringIO
from django.core.mail import EmailMultiAlternatives
# Generating the CSV
csvfile = StringIO()
writer = unicodecsv.writer(csvfile, encoding='utf-8')
writer.writerow([u'Test', u'Linebreak è'])
writer.writerow([u'Another', u'line'])
# Email
msg = EmailMultiAlternatives(
'csv report',
'Here is your attached report',
'email@from.com',
'email@to.com'
)
msg.attach('your_report.csv', csvfile.getvalue(), 'text/csv')
msg.send()
用VIM打开文件时,我看到的内容大概是这样的:
Test,Linebreak è^M
Another,line
如果CSV的行包含:
writer.writerow([u'Test', u'Linebreak'])
writer.writerow([u'Another', u'line'])
那么附件中的CSV看起来会是这样的:
Test,Linebreak
Another,line
getvalue()似乎输出了正确的换行格式,但在文件附加后似乎发生了一些问题。有没有人注意到类似的问题?
(我在使用Django 1.6和Python 2.7)
补充:我找到了问题的根源。原来我在用sendgrid发送邮件,出于某种原因,他们的系统在我的CSV中添加了额外的换行,当这个CSV包含重音字符时...
2 个回答
如果你使用Sendgrid作为SMTP服务来发送邮件,并且遇到类似的问题,我解决我的问题的方法是没有使用SMTP,而是通过Sendgrid的Web API来发送邮件(可以参考这个链接:https://github.com/elbuo8/sendgrid-django)。
现在我的CSV报告里没有多余的行了!
根据评论者的要求,我将提供一个使用Python标准SMTP库的解决方案,而不是SendGrid。
和原作者的代码一样,我们使用的是包含Unicode的CSV数据。当准备消息时,我们明确将数据作为UTF-8编码的文本附件添加,并像这样构建消息对象:
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# Write CSV data ...
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = sender
msg['To'] = recipients
msg.preamble = subject + '\n'
# Message body
body = MIMEText(body, 'plain', 'utf-8')
# CSV data
csv = MIMEText(csvfile.getvalue(), 'csv', 'utf-8')
csv.add_header("Content-Disposition", "attachment",
filename=report_filename)
# Add body and attachment to message
msg.attach(body)
msg.attach(csv)
你可以在Python库文档中了解更多关于MIMEText的信息。我发现传递Unicode字符串(而不是str
/bytes
)是有效的,只要正确声明了字符集。
另外,我要说明的是,我不确定换行问题是通过使用MIMEText附件解决的,还是因为编码的原因。使用MIMEText对象作为原作者代码中的附件可能会解决这个问题。不过,我把实验留给你去尝试。