如何判断字符串是否为Base64编码

7 投票
6 回答
11251 浏览
提问于 2025-04-11 09:36

我收到了很多来自不同来源的邮件。这些邮件都有附件,其中很多附件的名字是中文,所以这些名字在邮件客户端中被转换成了base64格式。

当我收到这些邮件时,我想解码这些名字。但是还有一些名字并不是base64格式的。我该如何判断一个字符串是否是base64格式,使用jython编程语言呢?

也就是说:

第一个附件:

------=_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格式。

6 个回答

7

@gnud, @edg - 除非我理解错了,他在问的是文件名,而不是文件内容。

@setori - Content-Transfer-Encoding 是在告诉你文件内容是怎么编码的,而不是“文件名”。

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

=?gb2312?B?

我在找相关的文档,RFC里有... 啊!找到了: https://www.rfc-editor.org/rfc/rfc2047

RFC里说:

一般来说,“编码词”是一个可打印的ASCII字符序列,它以“=?”开头,以“?=”结尾,中间有两个“?”。

另外可以看看SharpMimeTools里的代码,这是一个我在我的缺陷跟踪应用中使用的MIME解析器(用C#写的),BugTracker.NET

21

这个头部的值告诉你这些信息:

=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?=

"=?"     introduces an encoded value
"gb2312" denotes the character encoding of the original value
"B"      denotes that B-encoding (equal to Base64) was used (the alternative 
         is "Q", which refers to something close to quoted-printable)
"?"      functions as a separator
"uLG..." is the actual value, encoded using the encoding specified before
"?="     ends the encoded value

所以在"?"上进行分割实际上会得到这个(JSON格式)

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

在得到的数组中,如果"B"在第2个位置,那么第3个位置上会有一个经过Base64编码的字符串。解码后,记得关注第1个位置的编码信息,最好是根据这些信息把整个内容转换成UTF-8格式。

12

请注意,两个 Content-Transfer-Encoding 都是使用 base64 编码的。

在这种情况下,这个 Content-Transfer-Encoding 不太相关,它只适用于邮件的主体内容,而不是邮件的头部信息。

=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?=

这是一个经过 RFC2047 编码的头部信息。用来解码它的标准库函数是 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 编码只能出现在原子(atom)中,而引用字符串(quoted-string)并不是原子。RFC2047 第5条明确禁止这样做:

  • 一个“编码词”不能出现在“引用字符串”中。

当参数头部包含长字符串或 Unicode 字符时,正确的编码方式是 RFC2231,这又是一个复杂的问题。不过,你应该使用一个标准的邮件解析库,它会为你处理这些事情。

所以,如果你想的话,可以检测文件名参数中的 '=?',并尝试通过 RFC2047 解码它。然而,严格来说,正确的做法是相信邮件程序的说法,真的把文件称为 =?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?=

撰写回答