如何在 Ruby 中解码“=?UTF-8?B?…”字符串

问题描述 投票:0回答:2

我正在使用 Mandrill 入站电子邮件 API,当一封电子邮件的附件的文件名中包含一个或多个空格时,该文件名将以一种我不知道如何解码的格式进行编码。

这是我收到的文件名示例字符串:

=?UTF-8?B?TWlzc2lvbmFyecKgRmFpdGjCoFByb21pc2XCoGFuZMKgQ2FzaMKgUmVjZWlwdHPCoFlURMKgMjUzNQ==?= =?UTF-8?B?OTnCoEp1bHktMjAxNS5jc3Y=?=

我尝试了

Base64.decode64(#{encoded_value})
,但没有返回可读的文本。

如何将该值解码为可读字符串?

ruby mandrill
2个回答
3
投票

这是RFC-2822中定义的MIME编码字语法。来自维基百科:

形式为:“

=?
字符集
?
编码
?
编码文本
?=
”。

  • charset 可以是向 IANA 注册的任何字符集。通常它与消息正文具有相同的字符集。
  • encoding 可以是“
    Q
    ”表示类似于 quoted-printable 编码的 Q 编码,也可以是“
    B
    ”表示 base64 编码。
  • 编码文本是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"


1
投票

感谢@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
© www.soinside.com 2019 - 2024. All rights reserved.