Как сделать обалденный почтовый шаблон

April 14, 2011 ActionMailer CSS Ruby on Rails верстка почтовые рассылки

Недавно я был озабочен версткой (и подключением к Rails) целого комплекта шаблонов рассылок и почтовых уведомлений и решил извлечь из этого процесса наибольшую пользу.

Ниже мои наблюдения, в произвольном порядке – разумеется, со привкусом рельсы.

Общие рекомендации

Мой собственный опыт

Шаблон должен “работать” без картинок

В большинстве почтовых клиентов картинки загружаются только по запросу пользователя. Следовательно, шаблон должен заинтересовывать и без картинок.


Graceful degradation в применении к письмам

В данном случае кнопка сделана табличкой из единственной ячейки, грубо говоря, так:

<table>
  <tr><td width="100" height="50" bgcolor="red" background="button.png">
    <a href="#" style="width:100; height:50;padding:0;margin:0">Заказать</a>
  </td></tr>
</table>

Товарищи верстальщики, не приходилось еще верстать кнопку табличкой?

Особый случай – логотипы. Их обязательно нужно изображать текстом - лучше пусть будет “не по брендбуку”, чем его не будет совсем. К тому же, “почтовая” типографика позволяет достичь хороших результатов:


При создании этих логотипов не пострадал ни один пиксель

Используй хелперы!

Хелперы – решение самой страшной проблемы почтовых шаблонов: встроенного CSS! Достаточно на каждый привычный класс определать по хелперу, где-то таким образом:

module MailHelper
  def mail_h1(&block)
    content_tag(:div, {
      :style => 'font-size: 18px; font-weight: bold; margin-bottom: 21px; line-height: 21px'
    }, &block)
  end

  def mail_p(&block)
    content_tag(:div, {
      :style => 'font-size: 14px; margin-bottom: 21px; line-height: 21px'
    }, &block)
  end
end

Если приглядеться, то это решение можно упростить посредством метапрограммирования – в таком виде код настолько похож на CSS, что даже верстальщики смогут его дополнять:

module MailHelper
  TAGS = {
    :h1 => 'font-size: 18px; font-weight: bold; margin-bottom: 21px; line-height: 21px'
    :p => 'font-size: 14px; margin-bottom: 21px; line-height: 21px'
  }

  TAGS.keys.each do |tag_name|
    define_method "mail_#{tag_name}" do |&block|
      content_tag(:div, {:style => MailHelper::TAGS[tag_name]}, &block)
    end
  end
end

А ведь можно теги и в YAML-файл вынести, или даже написать более утонченный парсер – что лично я считаю абсолютно ненужным.

С такими хелперами в шаблоны возвращаются порядок и читабельность:

=mail_h1 do
  My Header

=mail_p do
  My Paragraph

Верстай DIV-ами (нет, не в том смысле)

Поскольку использовать CSS Reset природными путями в почте не выйдет, то проще всего отталкиваться от элемента, наименее обремененного стилями по умолчанию - от DIV. Семантичность почтовой верстки совершенно никому не нужна.

…А вот макетирование, колонки, выравнивание и т.п. надежнее как раз верстать таблицами.

Ссылки с указанием домена

Все абсолютно ссылки должны указывать домен. То есть быть указаны с помощью _url-методов, а не _path-методов. То есть вместо

link_to @item.title, @item

нужно писать

link_to @item.title, item_url(@item)

Отслеживание кампаний

Вещь первой необходимости, такая же, как подсчет посетителей на сайте. Скорее всего, тебе это нужно делать через Google Analytics. Для этого к ссылкам нужно навешивать ряд специальных параметров – можно это делать через default_url_options, а можно – небольшим хелпером. Мне первый вариант не нравится тем, что он заставляет вешать параметры на все ссылки.

# mail_helper.rb
def utm_url(url, utm_content='')
  utm_params = "utm_medium=email&utm_campaign=#{@campaign_name}&utm_source=#{@campaign_source||@campaign_name}"
  utm_params += "utm_content=#{utm_content}" unless utm_content.blank?
  if url.include? '?'
    url += '&' + utm_params
  else
    url += '?' + utm_params
  end
  url
end

# my_mailer.rb
def promo
  @campaign_name = 'promo_campaign'
  @campaign_source = 'promo_campaign_april'
end
# promo.html.haml
=link_to 'Click here plz ok', utm_url(item_url(@item), 'view_item')

Отписка

В трех словах – отписка должна быть. И работать. Дешево и сердито – отписка посредством плагина bounces-handler, который, при должной настройке, сможет обрабатывать и ошибки в доставке почты.

Проверка шаблонов

Если ты до сих пор каждый раз отсылаешь письмо, чтобы увидеть, как выглядит шаблон, у меня есть к тебе предложение. Или даже два.

Проверять шаблоны особым контроллером

class MailerTestController
  layout 'mailer'

  def registration
    @user = Factory(:user)
    render :text => MyMailer.registration(@user).body
  end

  # ... more actions
end

# routes.rb
get '/mail_test/:action', :controller => 'mailer_test'

Генерировать письма Rake-командой

task :mail_test => :environment do
  @user = Factory(:user)
  File.open('tmp/mail_test/registration.html','w'){|f| f.puts MyMailer.registration(@user).body}
  # ... more messages
end

Первый вариант лучше тем, что можно отрисовывать шаблон по нажатию F5, а второй – тем, что его можно запускать в тестовом окружении и не портить базу.

Я использую второй.

Да, для таких фабрик, разумеется, удобно будет использовать Выдумщика.

Письма все равно нужно проверять в почтовом клиенте!

Проверки в почтовых клиентах – увы, самая неудобная часть всей работы. И самая неизбежная.

Buy Me a Coffee at ko-fi.com