1

使用mail红宝石我收到这条消息:

mail.rb:22:in `encode': "\xC7" from ASCII-8BIT to UTF-8 (Encoding::UndefinedConversionError)
    from mail.rb:22:in `<main>'

如果我删除编码,我会收到一条消息 ruby

/var/lib/gems/1.9.1/gems/bson-1.7.0/lib/bson/bson_ruby.rb:63:in `rescue in to_utf8_binary': String not valid utf-8: "<div dir=\"ltr\"><div class=\"gmail_quote\">l<br><br><br><div dir=\"ltr\"><div class=\"gmail_quote\"><br><br><br><div dir=\"ltr\"><div class=\"gmail_quote\"><br><br><br><div dir=\"ltr\"><div dir=\"rtl\">\xC7\xE1\xE4\xD5 \xC8\xC7\xE1\xE1\xDB\xC9 \xC7\xE1\xDA\xD1\xC8\xED\xC9</div></div>\r\n</div><br></div>\r\n</div><br></div>\r\n</div><br></div>" (BSON::InvalidStringEncoding)

这是我的代码:

require 'mail'
require 'mongo'

connection = Mongo::Connection.new
db = connection.db("DB")
db = Mongo::Connection.new.db("DB")
newsCollection = db["news"]

Mail.defaults do
  retriever_method :pop3, :address    => "pop.gmail.com",
                          :port       => 995,
                          :user_name  => 'my_username',
                          :password   => '*****',
                          :enable_ssl => true
end
emails = Mail.last
#Checks if email is multipart and decods accordingly. Put to extract UTF8 from body
plain_part = emails.multipart? ? (emails.text_part ? emails.text_part.body.decoded : nil) : emails.body.decoded

html_part = emails.html_part ? emails.html_part.body.decoded : nil

mongoMessage = {"date" => emails.date.to_s , "subject" => emails.subject , "body" => plain_part.encode('UTF-8') }
msgID = newsCollection.insert(mongoMessage) #add the document to the database and returns it's ID
puts msgID

对于英语和希伯来语,它工作得很好,但似乎 gmail 正在发送具有不同编码的阿拉伯语。替换UTF-8ASCII-8BIT给出类似的错误。

plain_part用于普通电子邮件时,我得到相同的结果。我正在处理来自一个特定来源的电子邮件,因此我可以确信 html_part 不会导致错误。为了使它更加奇怪,阿拉伯语中的主题被完美呈现。我应该使用什么编码?

4

2 回答 2

2

如果您encode不使用选项,则会引发此错误,如果您的字符串假装是一种编码但包含来自另一个编码的字符。

以这种方式尝试:

plain_part.encode('UTF-8', {:invalid => :replace, :undef => :replace, :replace => '?'})

这会将给定编码的无效和未定义字符替换为“?”(更多信息)。如果这不足以满足您的需求,您需要找到一种方法来检查您的plain_part字符串是否有效。例如,您可以为此使用valid_encoding?更多信息)。

我最近偶然发现了一个类似的问题,我无法确定它到底是什么编码,所以我写了这个(可能有点谦虚)的方法。希望它可以帮助您,找到解决问题的方法。

def self.encode!(str)
  return nil if str.nil?

  known_encodings = %w(
    UTF-8
    ISO-8859-1
  )

  begin
    str.encode(Encoding.find('UTF-8'))
  rescue Encoding::UndefinedConversionError
    fixed_str = ""
    known_encodings.each do |encoding|
      fixed_str = str
      if fixed_str.force_encoding(encoding).valid_encoding?
        return fixed_str.encode(Encoding.find('UTF-8'))
      end
    end
    return str.encode(Encoding.find('UTF-8'), {:invalid => :replace, :undef => :replace, :replace => '?'})
  end
end
于 2012-11-02T23:53:02.903 回答
0

我找到了解决办法。

由于只会将特定的电子邮件发送到此帐户以供在此应用程序上使用,因此我可以完全控制格式。出于某种原因,邮件完美解码text/plain附件

所以:

emails.attachments.each do | attachment |
  if (attachment.content_type.start_with?('text/plain'))
    # extracting txt file
    begin
body = attachment.body.decoded
    rescue Exception => e
      puts "Unable to save data for #{filename} because #{e.message}"
    end
  end
end
mongoMessage = {"date" => emails.date.to_s , "subject" => emails.subject , "body" => body }
于 2012-11-03T03:00:23.163 回答