代码之家  ›  专栏  ›  技术社区  ›  Scott Stafford

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

  •  1
  • Scott Stafford  · 技术社区  · 7 年前

    我正在发送一封带有附件的电子邮件,该附件的文件名很长。为什么它会被换行符损坏,系统的哪个部分应该知道这些换行符应该被删除?

    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 回复  |  直到 7 年前
        1
  •  2
  •   Community PPrice    3 年前

    长标题字段的处理在中定义 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。每个标题字段应为 以展开的形式进行处理,以进一步理解句法和语义 评价

        2
  •  2
  •   Pang firemonkey    6 年前

    正如Leon的回答所解释的,Python正在实现RFCs中定义的折叠算法。

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

    为了获得更大的灵活性,可以实例化生成器实例并直接使用其flatte()方法。例如:

    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 signature 所以

    print(msg.as_string(maxheaderlen=256))

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

    在Python 3.6中, maxheaderlen公司 暴露在 email.message.EmailMessage.as_string signature (请注意,这是一个不同的类)。 maxheaderlen公司 现在默认为 None :除非指定值,否则标题行以78个字符换行。