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 для драгоценного камня есть пример раздела о чтении составных электронных писем.

Помимо методов 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%>Это отправит текст, написанный в текстовом редакторе электронной почты, как и на электронную почту.

Другие вопросы по тегам