【问题标题】:How to get decode this attachment filename with python?如何用python解码这个附件文件名?
【发布时间】:2015-05-13 04:34:57
【问题描述】:

我已经在我的代码中解码了很多电子邮件附件文件名。

但是这个特殊的文件名破坏了我的代码。

这是一个最小的例子:

from email.header import decode_header
encoded_filename='=?UTF-8?B?U2FsZXNJbnZvaWNl?==?UTF-8?B?LVJlcG9ydC5wZGY=?='
decoded_header=decode_header(encoded_filename) # --> [('SalesInvoiceQ1|\x04\xb5I\x95\xc1\xbd\xc9\xd0\xb9\xc1\x91\x98', 'utf-8')]
filename=str(decoded_header[0][0]).decode(decoded_header[0][1])

例外:

UnicodeDecodeError: 'utf8' codec can't decode byte 0xb5 in position 16: invalid start byte

不要问我怎么做的,但是 Thunderbird 能够将此文件名解码为:SalesInvoice-Report.pdf

我怎样才能像电子邮件客户端一样使用 python 解码?

【问题讨论】:

    标签: python decode email-attachments email-headers


    【解决方案1】:

    该标题中有 两个 Encoded-Word 部分。您必须检测一个结束和一个开始的位置:

    >>> print  decode_header(encoded_filename[:28])[0]
    ('SalesInvoice', 'utf-8')
    >>> print  decode_header(encoded_filename[28:])[0]
    ('-Report.pdf', 'utf-8')
    

    显然这就是 Thunderbird 在这种情况下所做的;将字符串拆分为=?encoding?data?= 块。 通常这些应该由\r\n(回车+换行)字符分隔,但在您的情况下,它们是混在一起的。如果您重新引入 \r\n 分隔符,则该值将正确解码:

    >>> decode_header(encoded_filename[:28] + '\r\n' + encoded_filename[28:])[0]
    ('SalesInvoice-Report.pdf', 'utf-8')
    

    您可以使用正则表达式来提取部分并重新引入分隔符:

    import re
    from email.header import decode_header
    
    quopri_entry = re.compile(r'=\?[\w-]+\?[QB]\?[^?]+?\?=')
    
    def decode_multiple(encoded, _pattern=quopri_entry):
        fixed = '\r\n'.join(_pattern.findall(encoded))
        output = [b.decode(c) for b, c in decode_header(fixed)]
        return ''.join(output)
    

    演示:

    >>> encoded_filename = '=?UTF-8?B?U2FsZXNJbnZvaWNl?==?UTF-8?B?LVJlcG9ydC5wZGY=?='
    >>> decode_multiple(encoded_filename)
    u'SalesInvoice-Report.pdf'
    

    当然,可能首先是您在读取标题的方式上存在错误。确保在提取 encoded_filename 值时不会意外破坏现有的 \r\n 分隔符。

    【讨论】:

    • 我给了你“奖励现有答案”的赏金。非常感谢! ... 需要 23 小时 ... Stackoverflow 的奇怪限制。
    • @guettli:谢谢!您实际上不必这样做,但它非常赞赏。这些限制是为了打击欺诈。如果您可以立即奖励社区,那么社区将没有机会审核用于为邪恶目的转移代表的赏金。并以这种方式看待它:在赏金期间的额外关注可能导致额外的赞成票,也许有人知道更好的问题解决方案。 :-)
    • 顺便说一句,我们已经在邮件标题中解析了数千个文件名。我猜客户端创建了损坏的编码。
    • @guettli:是的,如果客户端生成这些标头没有中间有 CRLF,那么这就是一个损坏的客户端。也可能是它使用行分隔符(正确或格式不正确)生成值,然后中间的 MTA 会“修复”该值等。无论哪种方式,您现在都必须处理后果。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-21
    • 2012-10-02
    • 2020-08-10
    • 2012-05-21
    相关资源
    最近更新 更多