我的网站上有一个报告功能,可以通过电子邮件发送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()似乎输出了正确的EOL格式化程序,但是一旦附加了文件,似乎就会出现这种情况。其他人是否注意到了类似的问题?
(在Python 2.7上运行Django 1.6)
编辑:我找到了问题的根源。事实证明我正在使用sendgrid发送我的电子邮件,并且由于某种原因,当我的CSV包含重音时,他们的系统会在我的CSV上添加额外的换行符......
答案 0 :(得分:5)
根据评论者的要求,我将添加一个涉及Python的stamdard SMTP库而不是SendGrid的解决方案。
与OP的代码一样,我们使用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 library documentation中详细了解MIMEText。我发现传递unicode字符串(而不是str
/ bytes
)只要有正确的delcared字符集就可以工作。
另外,我必须注意,我不确定是否通过使用MIMEText附件或编码来解决换行问题。在OP的代码中使用MIMEText对象作为附件可能会解决问题。不过,我会给你留下实验。
答案 1 :(得分:2)
对于那些使用Sendgrid作为SMTP提供商向您发送电子邮件的人,如果您发现了类似的问题,我通过不使用SMTP而不是使用Sendgrid的Web API(通过https://github.com/elbuo8/sendgrid-django)解决了我的问题。
我的CSV报告中不再有额外的行了!