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 に答える