如何在Ruby中解码字符串

时间:2015-12-15 14:16:48

标签: ruby mandrill

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

以下是我收到的文件名示例字符串:=?UTF-8?B?TWlzc2lvbmFyecKgRmFpdGjCoFByb21pc2XCoGFuZMKgQ2FzaMKgUmVjZWlwdHPCoFlURMKgMjUzNQ==?= =?UTF-8?B?OTnCoEp1bHktMjAxNS5jc3Y=?=

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

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

2 个答案:

答案 0 :(得分:2)

这是MIME encoded-word syntax中定义的RFC-2822。来自维基百科:

  

表单为:“=? 字符集 ? 编码 ? 编码文字 {{ 1}}”。

     
      
  • charset 可以是使用IANA注册的任何字符集。通常它与邮件正文是相同的字符集。
  •   
  • 编码可以是“?=”,表示与quoted-printable编码类似的Q编码,也可以是“Q”表示base64 } encoding。
  •   
  • 编码文本是Q编码或base64编码的文本。
  •   

幸运的是,您不需要为此编写解码器。 Mail宝石附带Mail::Encodings.value_decode方法,效果非常好且非常well-tested

B

它优雅地处理了许多你可能不会想到的边缘情况(直到你的应用程序试图处理它们并摔倒):

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"

如果您使用的是Rails,那么您已拥有Mail gem。否则,只需将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 )" 添加到您的Gemfile,然后gem "mail",然后在您的脚本中添加bundle install

答案 1 :(得分: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