Is there a way to decode q-encoded strings in Ruby?

只谈情不闲聊 提交于 2019-12-01 06:52:18
ankimal

I use this to parse email subjects:

You could try the following:

str = "=?UTF-8?Q?J=2E_Pablo_Fern=C3=A1ndez?="
if m = /=\?([A-Za-z0-9\-]+)\?(B|Q)\?([!->@-~]+)\?=/i.match(str)
        case m[2]
        when "B" # Base64 encoded
          decoded = Base64.decode64(m[3])
        when "Q" # Q encoded
          decoded = m[3].unpack("M").first.gsub('_',' ')
        else
          p "Could not find keyword!!!"
        end
        Iconv.conv('utf-8',m[1],decoded) # to convert to utf-8
end

Ruby includes a method of decoding Quoted-Printable strings:

puts "Pablo_Fern=C3=A1ndez".unpack "M"
# => Pablo_Fernández

But this doesn't seem to work on your entire string (including the =?UTF-8?Q? part at the beginning. Maybe you can work it out from there, though.

This is a pretty old question but TMail::Unquoter (or its new incarnation Mail::Encodings) does the job as well.

TMail::Unquoter.unquote_and_convert_to(str, 'utf-8' )

or

Mail::Encodings.unquote_and_convert_to( str, 'utf-8' )

Decoding on a line-per-line basis:

line.unpack("M")

Convert STDIN or file provided input of encoded strings into a decoded output:

if ARGV[0]
  lines = File.read(ARGV[0]).lines
else
  lines = STDIN.each_line.to_a
end

puts lines.map { |c| c.unpack("M") }.join

This might help anyone wanting to test an email. delivery.html_part is normally encoded, but can be decoded to a straight HTML body using .decoded.

test "email test" do
  UserMailer.confirm_email(user).deliver_now
  assert_equal 1, ActionMailer::Base.deliveries.size
  delivery = ActionMailer::Base.deliveries.last
  assert_equal "Please confirm your email", delivery.subject
  assert delivery.html_part.decoded =~ /Click the link below to confirm your email/ # DECODING HERE
end
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!