Rails - почта, получая тело в виде простого текста
Дано: message = Mail.new(params[:message])
как видно здесь: http://docs.heroku.com/cloudmailin
В нем показано, как получить message.body в виде HTML, как получить текстовую или текстовую версию?
Спасибо
5 ответов
Код выше:
message = Mail.new(params[:message])
создаст новый экземпляр почтового драгоценного камня из полного сообщения. Затем вы можете использовать любой из методов в этом сообщении, чтобы получить контент. Поэтому вы можете получить простой контент, используя:
message.text_part
или HTML с
message.html_part
Эти методы просто угадывают и находят первую часть в составном сообщении типа содержимого text/plain или text/html. CloudMailin также предоставляет их в качестве удобных методов через params[:plain] и params[:html]. Стоит помнить, что сообщение никогда не будет иметь простой или HTML-части. Может быть стоит использовать что-то вроде следующего, чтобы быть уверенным:
plain_part = message.multipart? ? (message.text_part ? message.text_part.body.decoded : nil) : message.body.decoded
html_part = message.html_part ? message.html_part.body.decoded : nil
В качестве примечания также важно извлечь кодировку содержимого из сообщения при использовании этих методов и убедиться, что выходные данные закодированы в нужный метод кодирования (например, UTF-8).
Что такое Mail
?
message
определенный в вопросе, кажется, является экземпляром того же Mail
или же Mail::Message
класс, который также используется в ActionMailer::Base
или в драгоценности почтальона.
Я не уверен, где это интегрировано в рельсы, но Стив Смит указал, что это определено в почтовом драгоценном камне.
- Раздел использования файла readme на github.
- Документация
Mail::Message
на rubydoc.info.
Извлечение части из составного электронного письма
В файле 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.
После добавления этого драгоценного камня в 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
Резюме
# 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
email = Mail.new(params[:message])
text_body = (email.text_part || email.html_part || email).body.decoded
Я использую это решение на плагине RedmineCRM Helpdesk
Я полагаю, что если вы позвоните message.text_part.body.decoded, то конвертируете его в UTF-8 для вас с помощью самоцвета Mail, хотя документация по этому вопросу не ясна на 100%.
Сохранить формат тела HTML в Rails USE <% = @ email.body.html_safe%>Это отправит текст, написанный в текстовом редакторе электронной почты, как и на электронную почту.