6

我有很多来自不同来源的电子邮件。他们都有附件,其中许多都有中文的附件名称,因此这些名称被他们的电子邮件客户端转换为base64。

当我收到这些电子邮件时,我希望解码名称。但还有其他名称不是 base64。如何使用jython编程语言区分字符串是否为 base64?

IE。

第一个附件:

------=_NextPart_000_0091_01C940CC.EF5AC860
Content-Type: application/vnd.ms-excel;
 name="Copy of Book1.xls"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="Copy of Book1.xls"

第二个附件:

------=_NextPart_000_0091_01C940CC.EF5AC860
Content-Type: application/vnd.ms-excel;
 name="=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?="  

请注意“ Content-Transfer-Encoding ”都有 base64

4

6 回答 6

21

标头值告诉您:

=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?=

“=?” 引入一个编码值
“gb2312”表示原始值的字符编码
“B”表示使用了 B 编码(等于 Base64)(替代
         是“Q”,它指的是接近引用可打印的东西)
“?” 用作分隔符
"uLG..." 是实际值,使用之前指定的编码进行编码
"?=" 结束编码值

所以分裂“?” 实际上得到你这个(JSON符号)

["=", "gb2312", "B", "uLGxvmhlbrixsb5nLnhscw==", "="]

在结果数组中,如果“B”在位置 2,你在位置 3 上面对一个 base-64 编码的字符串。一旦你解码它,一定要注意位置 1 上的编码,可能最好转换使用该信息将整个过程转换为 UTF-8。

于 2008-11-07T10:35:59.157 回答
12

请注意两者Content-Transfer-Encoding都有 base64

在这种情况下不相关,Content-Transfer-Encoding仅适用于正文有效负载,不适用于标头。

=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?=

那是一个RFC2047编码的标头原子。解码它的 stdlib 函数是email.header.decode_header. 不过,它仍然需要一些后处理来解释该函数的结果:

import email.header
x= '=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?='
try:
    name= u''.join([
        unicode(b, e or 'ascii') for b, e in email.header.decode_header(x)
    ])
except email.Errors.HeaderParseError:
    pass # leave name as it was

然而...

Content-Type: application/vnd.ms-excel;
 name="=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?="

这是完全错误的。哪个邮件程序创建了它?RFC2047 编码只能发生在原子中,并且带引号的字符串不是原子。RFC2047 §5 明确否认这一点:

  • “编码字”不得出现在“引用字符串”中。

当存在长字符串或 Unicode 字符时,对参数标头进行编码的公认方法是RFC2231,这是一个全新的伤害包。但是你应该使用一个标准的邮件解析库来为你解决这个问题。

因此,您可以根据需要检测'=?'文件名参数,并尝试通过 RFC2047 对其进行解码。但是,严格来说正确的做法是信守邮件并真正调用文件=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?=

于 2008-11-07T11:38:38.970 回答
7

@gnud,@edg - 除非我误解,否则他是在询问文件名,而不是文件内容 @setori - Content-Trasfer-Encoding 告诉您文件的内容是如何编码的,而不是“文件名”。

我不是专家,但文件名中的这一部分告诉他后面的字符:

=?gb2312?B?

我正在寻找 RFC 中的文档……啊!这里是:https ://www.rfc-editor.org/rfc/rfc2047

RFC 说:

通常,“编码字”是一系列可打印的 ASCII 字符,以“=?”开头,以“?=”结尾,中间有两个“?”。

其他要查看的是 SharpMimeTools 中的代码,这是我在错误跟踪应用程序BugTracker.NET中使用的 MIME 解析器(C# 中)

于 2008-11-07T10:24:32.753 回答
2

有比 bobince 的方法更好的方法来处理decode_header. 我在这里找到它:http: //mail.python.org/pipermail/email-sig/2007-March/000332.html

name = unicode(email.header.make_header(email.header.decode_header(x)))
于 2009-11-06T13:58:52.103 回答
0

好吧,您将电子邮件标题解析为字典。然后检查是否设置了 Content-Transfer-Encoding,以及它是否 = "base64" 或 "base-64"。

于 2008-11-07T10:17:08.820 回答
0

问题:“”“另外我实际上需要知道它是什么类型的文件,即 .xls 或 .doc 所以我确实需要解码文件名才能正确处理附件,但如上所述,jython 似乎不支持 gb2312 ,知道任何环岛吗?"""

数据:

Content-Type: application/vnd.ms-excel;
 name="=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?="

观察:

(1) 第一行表示 Microsoft Excel,所以.xls看起来比.doc

(2)

>>> import base64
>>> base64.b64decode("uLGxvmhlbrixsb5nLnhscw==")
'\xb8\xb1\xb1\xbehen\xb8\xb1\xb1\xbeg.xls'
>>>

(a) 扩展名似乎是.xls——不需要gb2312编解码器
(b) 如果你想要一个文件系统安全的文件名,你可以使用 base64 的“-_”变体,或者你可以对其进行百分比编码
(c ) 对于它的价值,文件名是XYhenXYg.xls其中 X 和 Y 是 2 个中文字符,它们一起表示“复制”,其余的是文字 ASCII 字符。

于 2010-06-02T08:14:45.810 回答