我正在使用 Mandrill 入站电子邮件 API,当一封电子邮件的附件的文件名中包含一个或多个空格时,该文件名将以一种我不知道如何解码的格式进行编码。
这是我收到的文件名示例字符串:
=?UTF-8?B?TWlzc2lvbmFyecKgRmFpdGjCoFByb21pc2XCoGFuZMKgQ2FzaMKgUmVjZWlwdHPCoFlURMKgMjUzNQ==?= =?UTF-8?B?OTnCoEp1bHktMjAxNS5jc3Y=?=
我尝试了
Base64.decode64(#{encoded_value})
,但没有返回可读的文本。
如何将该值解码为可读字符串?
这是RFC-2822中定义的MIME编码字语法。来自维基百科:
形式为:“
字符集=?
编码?
编码文本?
”。?=
- charset 可以是向 IANA 注册的任何字符集。通常它与消息正文具有相同的字符集。
- encoding 可以是“
”表示类似于 quoted-printable 编码的 Q 编码,也可以是“Q
”表示 base64 编码。B
- 编码文本是Q编码或base64编码文本。
幸运的是,您不需要为此编写解码器。 Mail gem 附带了一个
Mail::Encodings.value_decode
方法,该方法运行完美并且经过了 充分测试:
subject = "=?UTF-8?B?TWlzc2lvbmFyecKgRmFpdGjCoFByb21pc2XCoGFuZMKgQ2FzaMKgUmVjZWlwdHPCoFlURMKgMjUzNQ==?= =?UTF-8?B?OTnCoEp1bHktMjAxNS5jc3Y=?="
Mail::Encodings.value_decode(subject)
# => "Missionary Faith Promise and Cash Receipts YTD 253599 July-2015.csv"
它可以优雅地处理许多你可能不会想到的边缘情况(直到你的应用程序尝试处理它们并崩溃):
subject = "Re:[=?iso-2022-jp?B?GyRCJTAlayE8JV0lcyEmJTglYyVRJXMzdDwwMnEbKEI=?=\n =?iso-2022-jp?B?GyRCPFIbKEI=?=] =?iso-2022-jp?B?GyRCSlY/LiEnGyhC?=\n =?iso-2022-jp?B?GyRCIVolMCVrITwlXSVzIVskKkxkJCQ5ZyRvJDsbKEI=?=\n =?iso-2022-jp?B?GyRCJE43byRLJEQkJCRGIUolaiUvJSglOSVIGyhC?=#1056273\n =?iso-2022-jp?B?GyRCIUsbKEI=?="
Mail::Encodings.value_decode(subject)
# => "Re:[グルーポン・ジャパン株式会社] 返信:【グルーポン】お問い合わせの件について(リクエスト#1056273\n )"
如果您使用 Rails,您已经拥有 Mail gem。否则,只需将
gem "mail"
添加到您的 Gemfile,然后添加 bundle install
,然后在脚本中添加 require "mail"
。
感谢@Yevgeniy-Anfilofyev 的评论为我指明了正确的方向,我能够编写以下方法来正确解析编码值并返回 ASCII 字符串。
def self.decode(value)
# It turns out the value is made up of multiple encoded parts
# so we first need to split each part so we can decode them seperately
encoded_parts = name.split('=?UTF-8?B?').
map{|x| x.sub(/\?.*$/, '') }.
delete_if{|x| x.blank? }
encoded_parts.map{|x| Base64.decode64(x)}. # decode each part
join(''). # join the parts together
force_encoding('utf-8'). # force UTF-8 encoding
gsub("\xC2\xA0", " ") # remove the UTF-8 encoded spaces with an ASCII space
end