有没有办法在Ruby中解码q编码的字符串?
我在处理邮件,名字和主题有时是q编码的,比如:有没有办法在Ruby中解码q编码的字符串?,ruby,email,decoding,Ruby,Email,Decoding,我在处理邮件,名字和主题有时是q编码的,比如: =?UTF-8?Q?J=2E_Pablo_Fern=C3=A1ndez?= 有没有办法用Ruby解码它们?似乎TMail应该处理它,但它没有这样做。Ruby包含一种解码引用的可打印字符串的方法: puts "Pablo_Fern=C3=A1ndez".unpack "M" # => Pablo_Fernández 但这似乎对整个字符串(包括开头的=?UTF-8?Q?部分)都不起作用。不过,也许你可以从这里开始计算出来。我用它来解析电子邮件
=?UTF-8?Q?J=2E_Pablo_Fern=C3=A1ndez?=
有没有办法用Ruby解码它们?似乎TMail应该处理它,但它没有这样做。Ruby包含一种解码引用的可打印字符串的方法:
puts "Pablo_Fern=C3=A1ndez".unpack "M"
# => Pablo_Fernández
但这似乎对整个字符串(包括开头的
=?UTF-8?Q?
部分)都不起作用。不过,也许你可以从这里开始计算出来。我用它来解析电子邮件主题:
您可以尝试以下方法:
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
这是一个很老的问题,但是TMail::Unquoter(或者它的新化身Mail::Encodings)也可以解决这个问题
TMail::Unquoter.unquote_and_convert_to(str, 'utf-8' )
或
每行解码:
line.unpack("M")
将标准输入或文件提供的编码字符串输入转换为解码输出:
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
这可能有助于任何想要测试电子邮件的人。delivery.html\u部分通常是编码的,但可以使用
.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
最有效和最新的解决方案似乎是使用的
value\u decode
方法
下面是可以剪切和粘贴的Ruby代码,如果愿意的话。如果直接使用Ruby执行,它将运行测试,
Ruby./copy pasted.rb
。正如在代码中所做的那样,我使用这个模块作为对字符串核心类的细化
关于解决方案的几点意见:
.gsub(“”,“”)
。但是,我不认为这是正确的,并且可能会根据字符集导致错误的解码。表示“\uu
始终表示十六进制20
”,因此,首先将=20
替换为
,然后依赖解包结果似乎是正确的。(这也使实现更加优雅。)中也讨论了这一点
;但不会占用选项卡或换行符)在单个字符串中的多个Q编码短语之间,如stringtest_4
所示。这是因为指示多个Q编码短语必须通过线性空格相互分隔。根据您的使用情况,可能不需要吸收空格
code
允许意外引用的可打印代码(而不是[bBqQ]
),以便发生匹配,并且代码可能引发错误。这有助于我在处理文本时检测意外值。将名为capture的code
正则表达式更改为[bBqQ]
如果不希望出现此行为。(将不存在匹配项,并返回原始字符串。)
Regexp.last_match
作为gsub
块中的一种便利。如果在多线程代码中使用此选项,您可能需要小心,我没有考虑到这一点
要求“小型测试/自动运行”
模块QuotedPrintableDecode
类未处理的代码错误<标准错误
def初始化(代码)
超级(“未处理的引用可打印代码:'#{code}.”)
结束
结束
@@qp_text_regex=%r{
=\?\开头文字:`=`
(?[^\?]+)#字符集,例如“=?Windows-1252”中的“Windows-1252”`
\?#文字:``
(?[a-zA-Z])#编码,例如,`?Q`(`B`ase64)`中的“Q”;[BbQq]预期,其他人会提高
\?#文字:``
(?[^\?]+?)#编码文本,惰性(非贪婪)匹配,例如`?Foo_栏中的“Foo_栏”`
\?=#结束文字:`=`
(?:[]+(?==\?)?#如果后面跟着另一个Q编码,则可选分隔线性空白
}x#自由间距模式允许上述注释,也会更改空格匹配
细化字符串吗
def解码(至:“UTF-8”)
self.gsub(@@qp\u text\u regex)do
代码,发件人,text=Regexp.last\u match.values\u at(:code,:charset,:text)
q_p_字符集_to_字符集(代码、文本、发件人、收件人)
结束
结束
私有的
def q_p_charset_to_charset(代码、文本、发件人、收件人)
案例代码
当“q”,“q”
text.gsub(“”,“=20”).解包(“M”)
当“b”,“b”
文本。解包(“m”)
其他的
引发未处理的代码错误。新建(代码)
end.first.encode(到,从)
结束
结束
结束
类TestQPDecodetest "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
> Mail::Encodings.value_decode("=?UTF-8?Q?Greg_of_Google?=")
=> "Greg of Google"