在ruby / rails中使用gmail gem进行附件的字符编码问题

时间:2018-11-17 19:27:53

标签: ruby-on-rails ruby character-encoding gmail

我在做什么: 我正在Rails 4应用程序中使用gmail gem,以定期获取来自特定帐户的电子邮件附件。这是核心部分的摘录(为简单起见,此处仅考虑第一封电子邮件及其第一附件):

require 'gmail'

Gmail.connect(@user_email,@user_password) do |gmail|
    if gmail.logged_in? 
        emails = gmail.inbox.emails(:from => @sender_email)
        email = emails[0]
        attachment = email.message.attachments[0]
        File.open("~/temp.csv", 'w') do |file| 
            file.write(
                StringIO.new(attachment.decoded.to_s[2..-2].force_encoding("ISO-8859-15").encode!('UTF-8')).read
            )
        end
    end
end

附件的编码可能会有所不同。我当前遇到的特殊问题是芬兰语。它包含芬兰语字符和上标3个字符。

这是我希望在运行上述代码时得到的。 (这是通过gmail用户界面手动下载附件时得到的): This is what I expect to get (and what I get when I download the attachment manually)

问题出在哪里:

但是,我得到以下奇怪的结果。

来自cat temp.csv(对我来说不错): This is from a cat temp.csv (looks good)

使用nano temp.csv(在这里我不知道自己在看什么): This is what it looks like with nano temp.csv

这是temp.csv在Sublime Text(直接通过winscp)中打开的样子。第一行和一小部分看起来还可以,但是中文/日语字符: This is what temp.csv looks like opened in Sublime Text (via winscp)

这是temp.csv在记事本中的外观(通过winscp下载后)。看起来还不错,只是在每个字符之间插入了一个空格,新行似乎丢失了: what temp.csv looks like in Notepad

我尝试过的事情:

未成功尝试过:

  • .force_encoding(...)和所有不同的“ ISO-8859-x”字符集
  • force_encoding("ISO-8859-15").encode!('UTF-8')放在.read之外(可以但不能解决问题)
  • 无需先强制进行另一种编码即可将其编码为UTF-8,但这会导致Encoding::UndefinedConversionError: "\xC4" from ASCII-8BIT to UTF-8
  • 'wb'中用'w+b'File.open()进行二进制写入(这似乎对结果没有影响)。
  • 在stackoverflow和网络上搜索其他想法。

任何想法将不胜感激!

2 个答案:

答案 0 :(得分:0)

不漂亮,但现在对我有用。

重新编码后,我将字符串转换为char数组,然后删除我不想要的char,然后将其余的数组元素合并成一个字符串。

decoded_att = attachment.decoded
data = decoded_att.encode("UTF-8", "ISO-8859-1", invalid: :replace, undef: :replace).gsub("\r\n", "\n")

data_as_array = data.chars
data_as_array = data_as_array.delete_if {|i| i == "\u0000" || i == "ÿ" || i == "þ"}
data = data_as_array.join('').to_s

File.write("~/temp.csv", data.to_s)

这现在对我有用。但是,我不知道这些字符如何以附件结尾(文档开头的"ÿ""þ"以及其余所有字符之间的"\u0000")。

答案 1 :(得分:0)

似乎您需要执行 var re = new RegExp('^ *\\d+(?:\\.\\d+)+ *'+ country); 而不是attachment.body.decoded