Что такое Mail
?
Определенный в вопросе message
представляется экземпляром того же класса Mail
или Mail::Message
, который также используется в ActionMailer::Base
или в mailman gem .
Я не уверен, где это интегрировано в рельсы, но Стив Смит указал , что это определено в mail gem .
Извлечение детали из составного электронного письма
В файле readme для драгоценного камня есть пример раздела о чтении составных писем .
Помимо методов html_part
и text_part
, которые просто находят первую часть соответствующего типа MIME , можно обращаться к деталям и просматривать их вручную, а также фильтровать по критериям.
message.parts.each do |part|
if part.content_type == 'text/plain'
# ...
elsif part.content_type == 'text/html'
# ...
end
end
Mail::Part
задокументировано здесь .
Проблемы с кодировкой
В зависимости от источника полученной почты могут возникнуть проблемы с кодировкой. Например, рельсы могут идентифицировать неправильный тип кодировки. Если затем попытаться преобразовать тело в UTF-8, чтобы сохранить его в базе данных (body_string.encode('UTF-8')
), могут быть ошибки кодирования, например
Encoding::UndefinedConversionError - "\xFC" from ASCII-8BIT to UTF-8
(как в этот вопрос ).
Чтобы обойти это, можно прочитать кодировку из части сообщения и сообщить rails, какой кодировкой она была до кодирования в UTF-8:
encoding = part_to_use.content_type_parameters['charset']
body = part_to_use.body.decoded.force_encoding(encoding).encode('UTF-8')
Здесь метод decoded
удаляет строки заголовка, как показано в разделе кодировки в readme .
почтового гема.
РЕДАКТИРОВАТЬ: проблемы жесткого кодирования
Если есть действительно сложные проблемы с кодированием, прежний подход не решает, взгляните на превосходный charlock_holmes gem .
После добавления этого драгоценного камня в Gemfile
существует более надежный способ преобразования кодировок электронной почты, используя метод detect_encoding
, который добавляется в строки этим драгоценным камнем.
Мне было полезно определить метод body_in_utf8
для почтовых сообщений. (Mail::Part
также наследуется от Mail::Message
.):
module Mail
class Message
def body_in_utf8
require 'charlock_holmes/string'
body = self.body.decoded
if body.present?
encoding = body.detect_encoding[:encoding]
body = body.force_encoding(encoding).encode('UTF-8')
end
return body
end
end
end
*
Резюме * 1081
# select the part to use, either like shown above, or as one-liner
part_to_use = message.html_part || message.text_part || message
# readout the encoding (charset) of the part
encoding = part_to_use.content_type_parameters['charset'] if part_to_use.content_type_parameters
# get the message body without the header information
body = part_to_use.body.decoded
# and convert it to UTF-8
body = body.force_encoding(encoding).encode('UTF-8') if encoding
РЕДАКТИРОВАТЬ: Или, после определения метода body_in_utf8
, как показано выше, так же, как однострочный:
(message.html_part || message.text_part || message).body_in_utf8