为什么Python的MIMEMultipart会生成带换行符的附件文件名?

时间:2018-01-20 18:13:58

标签: python mime

我发送的是附件附件的电子邮件,该附件的文件名很长。为什么它会被换行符损坏,应该删除系统应该知道哪些新行?

from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from email.utils import formatdate

msg = MIMEMultipart()
msg['Subject'] = 'subject'
msg['To'] = 'a@example.com'
msg['From'] = 'b@example.com'
msg['Date'] = formatdate(localtime=True)
msg.attach(MIMEText('abc'))

attachment_name = 'abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz.txt'
part = MIMEApplication("sometext", Name=attachment_name)
part['Content-Disposition'] = 'attachment; filename="%s"' % attachment_name
msg.attach(part)

print msg.as_string()

给我:

Content-Type: multipart/mixed; boundary="===============1448866158=="
MIME-Version: 1.0
Subject: subject
To: a@example.com
From: b@example.com
Date: Sat, 20 Jan 2018 13:11:42 -0500

--===============1448866158==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

abc
--===============1448866158==
Content-Type: application/octet-stream;
 Name="abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz
 abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz
 abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz.txt"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="abcdefghijklmnopqrstuvwxyz
 abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz
 abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz
 abcdefghijklmnopqrstuvwxyz.txt"

c29tZXRleHQ=
--===============1448866158==--

2 个答案:

答案 0 :(得分:2)

长标头字段的处理在section 2.2.3 of RFC 2822 "Internet Message Format"中定义。该部分在过时的RFC 5322中保持不变。

  

2.2.3。长标题字段

     

每个标题字段在逻辑上是包含的单行字符   字段名称,冒号和字段正文。为了方便   但是,为了处理每行的998/78字符限制,   标题字段的字段主体部分可以分成多个   线表示;这被称为“折叠”。一般规则是   这个标准允许折叠白色空间的地方(不是简单的   WSP字符),可以在任何WSP之前插入CRLF。例如,   标题字段:

     
Subject: This is a test
     

可以表示为:

     
Subject: This
 is a test
     

注意:虽然结构化的字段主体是以这样的方式定义的   折叠可以发生在许多词汇标记之间(甚至是   在一些词法标记中),折叠应该限制为   将CRLF置于更高级别的句法中断。例如,如果是   字段主体定义为逗号分隔值,建议使用   折叠发生在逗号分隔结构化项目之后   喜欢可以折叠场地的其他地方,即使它   允许在其他地方使用。

     

从这个折叠的多行表示移动的过程   调用其单行表示的头字段   “展开”。只需删除任何CRLF即可完成展开   WSP紧随其后。每个标题字段应该是   以展开的形式对待进一步的句法和语义   评价。

答案 1 :(得分:2)

正如Leon的回答所解释的那样,Python正在实施RFC中定义的折叠算法。

在Python 2中,您可以使用email.generator.Generator实例来控制最大标头长度;来自the docs

  

为了获得更大的灵活性,请实例化Generator实例并直接使用其flatten()方法。例如:

from cStringIO import StringIO
from email.generator import Generator
fp = StringIO()
g = Generator(fp, mangle_from_=False, maxheaderlen=60)
g.flatten(msg)
text = fp.getvalue()

(将maxheaderlen设置为零可以防止在几乎所有情况下折叠长标题行。)

在Python 3.5中,maxheaderlen参数在email.message.Message.as_string的{​​{3}}中公开,所以

print(msg.as_string(maxheaderlen=256))

是可能的。默认情况下,maxheaderlen为零,因此除非提供值,否则不会删除标题行。

在Python 3.6中,maxheaderlen的{​​{3}}中显示了email.message.EmailMessage.as_string(请注意,这是一个不同的类)。 maxheaderlen现在默认为None:标题行换行为78个字符,除非指定了值。