有没有办法在Ruby中解码q编码的字符串?

时间:2010-08-13 04:43:08

标签: ruby email decoding

我正在使用邮件,名称和主题有时会进行q编码,如下所示:

=?UTF-8?Q?J=2E_Pablo_Fern=C3=A1ndez?=

有没有办法在Ruby中解码它们?似乎TMail应该照顾它,但它没有这样做。

7 个答案:

答案 0 :(得分:6)

我用它来解析电子邮件主题:

您可以尝试以下方法:

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

答案 1 :(得分:3)

Ruby包含一种解码Quoted-Printable字符串的方法:

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

但是这似乎不适用于你的整个字符串(包括开头的=?UTF-8?Q?部分。也许你可以从那里开始工作。

答案 2 :(得分:2)

这是一个非常古老的问题,但TMail :: Unquoter(或其新的化身Mail :: Encodings)也可以完成这项工作。

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

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

答案 3 :(得分:0)

以每行为单位进行解码:

ng build

将STDIN或文件提供的编码字符串输入转换为解码输出:

line.unpack("M")

答案 4 :(得分:0)

这可能会帮助想要测试电子邮件的任何人。 delivery.html_part通常经过编码,但可以使用.decoded解码为纯HTML正文。

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

答案 5 :(得分:0)

最有效和最新的解决方案似乎是使用Mail gemvalue_decode方法。

> Mail::Encodings.value_decode("=?UTF-8?Q?Greg_of_Google?=")
=> "Greg of Google"

https://www.rubydoc.info/github/mikel/mail/Mail/Encodings#value_decode-class_method

答案 6 :(得分:0)

以下是您可以剪切和粘贴的 Ruby 代码,如果愿意的话。如果直接使用 ruby​​ end 执行,它将运行测试。正如代码中所做的那样,我使用这个模块作为对 String 核心类的改进。

关于解决方案的几点说明:

  1. 其他解决方案对解压后的字符串执行 ruby ./copy-pasted.rb。但是,我认为这是不正确的,并且根据字符集可能导致解码不正确。 RFC2047 Section 4.2 (2) 表示“.gsub('_', ' ') 始终代表十六进制 _”,因此首先将 20 替换为 =20 然后依赖解包结果似乎是正确的。 (这也使实现更加优雅。)这也在 an answer to a related question 中讨论。

  2. 为了更有指导意义,我以自由间距模式编写了正则表达式以允许注释(我发现这通常对复杂的正则表达式很有帮助)。如果您调整正则表达式,请注意自由间距模式会更改空白的匹配,然后必须将其转义或作为字符类(如代码中)完成。我也有 added the regular expression on regex101,因此您可以阅读对命名捕获组、惰性量词等的解释并自己进行实验。

  3. 正则表达式将占用单个字符串中多个 Q 编码短语之间的空格(_;但不占用 或换行符),如字符串 TAB 所示。这是因为 RFC2047 Section 5 (1) 表示多个 Q 编码的短语必须通过线性空白相互分隔。根据您的用例,可能不需要吸收空白。

  4. 名为 capture 的正则表达式 test_4 允许意外引用的可打印代码(除 code 之外,以便发生匹配并且代码可能引发错误。这有助于我检测意外值处理文本时。如果您不希望出现这种行为,请将 [bBqQ] 的名为 capture 的正则表达式更改为 code。(将不匹配并返回原始字符串。)

  5. 它利用全局 [bBqQ] 作为 Regexp.last_match 块中的便利。如果在多线程代码中使用它,您可能需要小心,我没有考虑过这一点。

其他参考和阅读:

gsub