如何在Ruby中解码RFC 2047编码的电子邮件头?

时间:2011-09-20 17:01:41

标签: ruby encoding tmail

我有以下标题:

From: =?iso-8859-1?Q?Marta_Falc=E3o?= <marta.falcao@example.com.br>

我可以轻松地在<之前拆分这些东西,这留给我

"=?iso-8859-1?Q?Marta_Falc=E3o?="

我可以使用哪些内容将其转换为"Marta Falcão"

3 个答案:

答案 0 :(得分:8)

使用较新的Mail gem:

Mail::Encodings.value_decode(str)Mail::Encodings.unquote_and_convert_to(str, to_encoding)

答案 1 :(得分:3)

感谢Roland Illig的评论,这让我有两个选择:

  1. 安装rfc2047-ruby并致电Rfc2047.decode(header)
  2. 安装TMail并致电TMail::Unquoter.unquote_and_convert_to(header, 'utf-8')或更好TMail::Address.parse(header).friendly,后者删除了<email address>部分

答案 2 :(得分:0)

使用Ruby实现RFC 2047并不难:

module Rfc2047
  TOKEN = /[\041\043-\047\052\053\055\060-\071\101-\132\134\136\137\141-\176]+/.freeze
  ENCODED_TEXT = /[\041-\076\100-\176]+/.freeze
  ENCODED_WORD = /=\?(?<charset>#{TOKEN})\?(?<encoding>[QB])\?(?<encoded_text>#{ENCODED_TEXT})\?=/i.freeze

  class << self
    def encode(input)
      "=?#{input.encoding}?B?#{[input].pack('m0')}?="
    end

    def decode(input)
      match_data = ENCODED_WORD.match(input)
      raise ArgumentError if match_data.nil?

      charset, encoding, encoded_text = match_data.captures
      decoded =
        case encoding
        when 'Q', 'q' then encoded_text.unpack1('M')
        when 'B', 'b' then encoded_text.unpack1('m')
        end
      decoded.force_encoding(charset)
    end
  end
end
Rfc2047.decode '=?iso-8859-1?Q?Marta_Falc=E3o?=' # => Marta_Falcão

更新

mikel/mail当前有一个encoding issue,可能无法正确解码该字符串。

如果这确实困扰您,您可以尝试new_rfc_2047

$ gem install new_rfc_2047
$ ruby -rrfc_2047 -e 'puts Rfc2047.decode "From: =?iso-8859-1?Q?Marta_Falc=E3o?= <marta.falcao@example.com.br>"'
From: Marta Falcão <marta.falcao@example.com.br>

由于mikel / mail的源代码对于我来说太复杂了,无法进行修改,因此我为此制作了自己的gem。

宝石来源在这里:https://github.com/tonytonyjan/rfc_2047/