Как обрабатывать заголовки электронной почты UTF-8 (например, Subject:) с помощью Ruby?

У меня электронная почта n00b, но я работаю над приложением, которое отправляет электронную почту в формате HTML с символами Unicode (как заметил мой друг, «наслаждайтесь адским кодированием»).

Заголовок Subject: поступает из пользовательского ввода и поэтому может содержать символы Unicode. Некоторые почтовые клиенты (такие как GMail и Outlook 2007) поддерживают это, но, насколько я читал, правильный способ сделать это — использовать Кодировка MIME Encoded-Word для заголовков.

Я не могу найти библиотеку Ruby для этого. Есть ли один?

Кроме того, нужно ли добавить заголовок, который будет указывать почтовым клиентам использовать UTF-8 при отображении сообщения? Мы отправляем составное электронное письмо, поэтому наш Content-Type равен multipart/mixed. В частности, Apple Mail.app не использует правильную кодировку, хотя в отдельных частях она указана как UTF-8.


person Luke Francl    schedule 04.12.2008    source источник


Ответы (3)


При желании вы можете сделать то же самое, используя кодировку Base64:

require "base64"

value  = Base64.encode64("Your UTF-8 string")
header = "=?UTF-8?B?" + value + "?="

Обратите внимание на букву «B», которая обозначает полезную нагрузку в кодировке Base64, в отличие от «Q», которая отмечает полезную нагрузку в кодировке «Q». Последнее можно подделать, закодировав строку в URL и заменив все символы «%» на «=».

Под «подделкой» я подразумеваю следующее: это даст правильный результат, но, возможно, будет закодировано больше символов, чем необходимо. Спецификация позволяет кодировать каждый символ с помощью "=" + ByteCodeAsHex, это просто ухудшает читаемость необработанных заголовков человеком. UrlEncode + .gsub(/%/, "=") неплохой компромисс, когда ничего другого нет.

person Tomalak    schedule 04.12.2008
comment
Спасибо! Я начал с использования Base64, но я беспокоился о том, что спам-фильтры помечают это, поэтому я переключился на кавычки для печати. Я нашел способ сделать это в ActionMailer::Quoting. Похоже, это тоже работает! - person Luke Francl; 04.12.2008
comment
Я не думаю, что спам-фильтры пометят это, это допустимое значение заголовка. - person Tomalak; 04.12.2008
comment
Да, у меня нет никаких доказательств этого. Я думал, что спамеры могут попытаться обойти наивные фильтры контента. - person Luke Francl; 05.12.2008
comment
Кодированный Q должен быть упакован. например, str.to_a.pack(M) или что-то в этом роде. См. это для декодирования: «Есть ли способ декодировать закодированные строки q в ruby»> stackoverflow.com/questions/3473952/ - person ankimal; 03.12.2011

Ах ах! ActionMailer::Quoting имеет метод quoted_printable.

Итак, вот что я сделал:

def my_email(foo)
  ...
  @subject = quoted_printable(foo.some_subject_with_accented_chars, 'utf-8')
  ...
end

Это убедило Mail.app отображать остальную часть электронной почты, используя кодировку UTF-8. Остальных теперь тестить!

person Luke Francl    schedule 04.12.2008
comment
Этот метод не существует в рельсах 4 :( - есть альтернатива? - person Hackeron; 03.04.2014

Поскольку ни один из ответов не говорит о полном сообщении с чистым Ruby, вот оно.

Net::SMTP.start("localhost") do |smtp|
    smtp.open_message_stream opts[:sender_address], opts[:receiver_address] do |f|

        f.puts "Content-type: text/plain; charset=UTF-8"
        f.puts from
        f.puts to
        f.puts subject
        f.puts message
    end
end

Здесь вы открываете соединение с локальным хостом. Также возможно использование внешнего SMTP-сервера, см. документацию net/smtp.

Первая строка устанавливает набор символов, используемый в сообщении. Остальные строки являются переменными, определенными отдельно:

from — это адрес в форме From: Name here <[email protected]>. Если имя не требуется, можно указать только адрес, например From: [email protected].

to использует тот же синтаксис, за исключением того, что From: изменено на To:.

тема в форме Тема: тема здесь. Для UTF-8 он должен быть закодирован в Base64, чтобы правильно отображаться для клиентов.

subject = "Subject: =?UTF-8?B?" + Base64.strict_encode64(subject) + "?="

Сообщение представляет собой обычное текстовое сообщение в кодировке UTF-8 без префикса. net/smtp позаботится о правильном формировании почты.

person Smar    schedule 14.09.2011