我正在使用邮件,名称和主题有时会进行q编码,如下所示:
=?UTF-8?Q?J=2E_Pablo_Fern=C3=A1ndez?=
有没有办法在Ruby中解码它们?似乎TMail应该照顾它,但它没有这样做。
答案 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 gem的value_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 核心类的改进。
关于解决方案的几点说明:
其他解决方案对解压后的字符串执行 ruby ./copy-pasted.rb
。但是,我认为这是不正确的,并且根据字符集可能导致解码不正确。 RFC2047 Section 4.2 (2) 表示“.gsub('_', ' ')
始终代表十六进制 _
”,因此首先将 20
替换为 =20
然后依赖解包结果似乎是正确的。 (这也使实现更加优雅。)这也在 an answer to a related question 中讨论。
为了更有指导意义,我以自由间距模式编写了正则表达式以允许注释(我发现这通常对复杂的正则表达式很有帮助)。如果您调整正则表达式,请注意自由间距模式会更改空白的匹配,然后必须将其转义或作为字符类(如代码中)完成。我也有 added the regular expression on regex101,因此您可以阅读对命名捕获组、惰性量词等的解释并自己进行实验。
正则表达式将占用单个字符串中多个 Q 编码短语之间的空格(_
;但不占用
或换行符),如字符串 TAB
所示。这是因为 RFC2047 Section 5 (1) 表示多个 Q 编码的短语必须通过线性空白相互分隔。根据您的用例,可能不需要吸收空白。
名为 capture 的正则表达式 test_4
允许意外引用的可打印代码(除 code
之外,以便发生匹配并且代码可能引发错误。这有助于我检测意外值处理文本时。如果您不希望出现这种行为,请将 [bBqQ]
的名为 capture 的正则表达式更改为 code
。(将不匹配并返回原始字符串。)
它利用全局 [bBqQ]
作为 Regexp.last_match
块中的便利。如果在多线程代码中使用它,您可能需要小心,我没有考虑过这一点。
其他参考和阅读:
gsub