Статьи

Веселая отправка почты по рельсам

Корабль викингов

Рискнув с самим собой, я помню наш мир без электронной почты. Это было время изоляции, когда для асинхронной связи требовались «автоответчики» или «факсы». По-настоящему отчаявшиеся повернулись к ручке и бумаге, требуя, чтобы группа грузовиков и самолетов обеспечивала прибытие сообщения в пункт назначения. Ох, и самый страшный аспект этих темных дней? Спам был переработанным мясом, которое (якобы) ЛЮДИ АТЕ!

содрогается

К счастью, мы прошли долгий путь с тех времен. Электронная почта взяла мир штурмом, поднявшись от инструментов гика до инструмента непрофессионала в стратосферу раздражающего инструмента, используемого маркетологами и ворами. Независимо от многих предсказаний о гибели электронной почты в качестве механизма коммуникации, она остается здесь. Мы все используем его, и, как разработчику Rails, вам, несомненно, понадобится поговорить с вашими пользователями и отправить им переработанное мясо. НЕТ! Я имею в виду невероятно важные коммюнике, которые будут улучшать их жизнь каждый день!

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

Основы

Rails использует модуль ActionMailer для обработки электронной почты. Руководство по ActionMailer отлично, и его стоит прочитать. Я расскажу о том, через что проходит руководство, но вы должны прочитать их сами.

Создание почтовика

Для отправки почты Rails требуется один или несколько «почтовиков», которые являются подклассами ActionMailer::Base .

 class VikingMailer < ActionMailer::Base # Default Mail Values default from: '[email protected]', to: { User.pluck(:email) } end 

В приведенном фрагменте я добавил пару значений по умолчанию. Вы можете переопределить эти значения в отдельных методах почтовой программы. Другие элементы, которые могут иметь значения по умолчанию, являются subject и headers .

Хорошая идея использовать генератор Rails для создания почтовой программы

 rails g mailer VikingAMailer create app/mailers/viking_mailer.rb invoke erb create app/views/viking_mailer invoke test_unit create test/mailers/viking_mailer_test.rb create test/mailers/previews/viking_mailer_preview.rb 

Генератор создает файл почтовой программы, папку просмотра для почтовой программы, тестовый файл и файл предварительного просмотра для почтовой программы. Похоже на генерацию контроллера, не так ли? Это.

Каждый метод в классе Mailer подобен методам на контроллере Rails. Если вы хотите отправить приветственное письмо новым пользователям, добавьте метод welcome_email в свой класс почтовой программы вместе с представлением с тем же именем в каталоге app / views / viking_mailer .

 class VikingMailer < ActionMailer::Base # Default Mail Values default from: '[email protected]', to: { User.pluck(:email) } def welcome_email(user) @user = user # I am overriding the 'to' default mail(to: @user.email, subject: 'Do you have any spam?') end end 

Файл app / views / viking_mailer / welcome_email.html.erb может выглядеть следующим образом:

 <p>Dear <%= @user.name %>,</p> <p>We want Spam for breakfast.</p> <p>Yours truly,</p> <p>Bloody Vikings</p> 

Обратите внимание, @user экземпляра @user доступна в представлении, как и обычные контроллеры и представления. Кстати, почтовые представления также могут иметь макеты.

Пока мы находимся на теме представлений, можно указать формат представления электронной почты, так же как представления Rails. Выше вид был welcome.html.erb . Если мы добавим welcome.text.erb, ActionMailer добавит его в исходящее сообщение MIME. Это обеспечивает контроль над текстовой и HTML-версией вашей электронной почты, что воплощает ваши самые смелые мечты MIME.

конфигурация

Чтобы отправить электронное письмо, необходимо правильно настроить ActionMailer. Существует несколько способов отправки электронной почты, но наиболее распространенным способом является SMTP-протокол.

Вот хорошая статья об основах SMTP.

Типичный пример конфига из руководств:

 config.action_mailer.delivery_method = :sendmail # Defaults to: # config.action_mailer.sendmail_settings = { # location: '/usr/sbin/sendmail', # arguments: '-i -t' # } config.action_mailer.perform_deliveries = true config.action_mailer.raise_delivery_errors = true config.action_mailer.default_options = {from: '[email protected]'} 

Эта конфигурация будет использовать программу отправки [email protected] UNIX, поднимать ошибки доставки и делать отправителя по умолчанию [email protected] . Опция perform_deliveries — это, как вы уже догадались, способ сказать Rails не отправлять почту никогда. В некоторых ситуациях, например в среде разработки, вы можете не захотеть отправлять почту.

Следующий уровень

Давай займемся делами, не так ли? Теперь, когда вы понимаете основы отправки электронной почты, что еще можно сделать? Много.

Заголовки

Одна из частей «электронной почты» — это заголовок. Он состоит из таких полей, как адреса и / или адреса, тема, идентификатор сообщения и даты отправки. Есть много других , которые вы можете передать в качестве аргумента хеша методу mail :

 def welcome_email(user) ...rest of method... mail(to: @user.email, subject: "Word", reply_to: '[email protected]') end 

Фактически, метод mail принимает только один хеш-параметр для заголовков, параметров доставки и шаблонов. Под «delivery_options» я имею в виду, что вы можете указать настройки почтовой SMTP, которые обычно находятся в конфигурации приложения Rails. Параметры шаблона — это, например, путь к вашим почтовым шаблонам.

Указание формата Inline

Метод mail принимает только хеш. Ну, это и блок. Вы можете передать блок методу mail чтобы указать, как обрабатывать определенные форматы.

 def welcome_email(user) ...rest of method... mail(to: @user.email, subject: "Word", reply_to: '[email protected]') do |format| format.html { render 'cool_html_template'} format.text { render text: 'Get a real mail client!'} end end 

Теперь он действительно выглядит как контроллер Rails. Эта команда Rails уверена, что она умная!

Необычный формат адреса электронной почты

Если у вас есть имя получателя, не стесняйтесь отформатировать ваш адрес электронной почты следующим образом:

 #{@user.name} <#{@user.email}> 

Пользователь будет чувствовать, что вы действительно их знаете, а не Spammy McSpammer.

Вложения

Что хорошего в электронной почте, если вы не можете отправлять вложения? К счастью, ActionMailer упрощает отправку вложений. Просто добавьте File в хэш attachments внутри вашего метода Mailer.

 def welcome_email(user) attachments["viking-breakfast.mp4"] = File.read('spamspamspam.mp4') mail.... end 

Теперь видео викингов будет отображаться в виде вложения в электронное письмо. Но как насчет встроенных вложений?

Вы спрашиваете, что такое встроенные вложения? Только самая лучшая вещь со вкусом обработанного мяса! Лучший пример — изображение в вашем супер-необычном электронном письме в формате HTML. Встроенные вложения — это то, что позволяет вам включать это изображение в контент электронной почты, а не свисать с конца, как какое-то глупое видео с кошкой или файл .dot (что, черт возьми, это вообще?).

К счастью, добавить встроенные вложения так же просто:

 attachments.inline['viking-header.jpg'] = File.read('viking-header.jpg') 

Затем, по вашему мнению, сделайте это:

 <%= image_tag attachments['viking-header.jpg'].url %> 

И ваше HTML-письмо обязательно привлечет их внимание.

Перехватчики

Перехватчики являются крюками в процессе отправки электронной почты. ActionMailer предоставляет эту платформу, позволяющую изменять электронную почту до того, как она уйдет в Интернет. Вы спросите, почему вы хотите это сделать? Хороший ответ таков: не позволяйте вашей промежуточной / QA-среде отправлять электронные письма вашим пользователям. Может быть создан перехватчик для проверки среды Rails (разработка, производство, подготовка) и отправки электронного письма на промежуточный адрес вместо предполагаемого получателя. Теперь вы можете посмотреть, как выглядит электронная почта, прежде чем выпускать ее в производство. Позже я покажу вам драгоценный камень, который делает именно это.

Чтобы создать перехватчик, определите класс Ruby, напишите метод hook и добавьте перехватчик в конфигурацию.

 # From the guides class VikingEmailInterceptor def self.delivering_email(message) message.to = ['[email protected]'] message.subject = "We don't have any!" end end 

Затем в инициализаторе (например, config / initializers / viking_email_interceptor.rb ):

 ActionMailer::Base.register_interceptor(VikingEmailInterceptor) if Rails.env.staging? 

Теперь все ваши письма будут VikingEmailInterceptor и они будут отправляться только по адресу «[email protected]».

Отправка электронной почты асинхронно

Отправка электронной почты в большинстве случаев является операцией «забыл и забыл». Может быть некоторая задержка при вызове почтового сервера или создании почтового представления или чего-либо еще. Отправка почты асинхронно часто желательна, так как это означает, что пользователю не нужно ждать чего-то, что он не увидит в приложении.

В Rails 3.x — 4.1.x задача фоновой электронной почты ложится на разработчика. Вот отличный пример того, как сделать это с Sidekiq . Это будет работать в Rails 3 или 4, но вы должны иметь Sidekiq (и, следовательно, Redis), настроенный и готовый к работе.

Rails 4.2 обеспечивает это немного проще с ActiveJob . ActiveJob является стандартным фасадом для различных систем очередей, таких как Sidekiq , Resque или Delayed Job . Первый метод в Rails, использующий преимущества новой очереди ActiveJob, — это метод delivery_later в ActionMailer! Конечно, вам нужно будет настроить одну из вышеупомянутых систем очередей, но как только вы это сделаете, фоновая обработка вашей электронной почты будет простой.

Кстати, если вам нужна помощь в выборе или настройке системы массового обслуживания, ознакомьтесь с этой серией !

Сервисы

Электронная почта — это большой, большой, большой бизнес. Таким образом, вы, вероятно, захотите узнать, достигают ли ваши электронные письма ваших викингов, открываются ли они, сколько электронных писем вы отправляете и т. Д. Если вы настроили приложение Rails для использования локального SMTP-сервера с sendmail, то масштабируйте и отслеживание трудно или невозможно. Использование службы централизует отправку вашей электронной почты и предоставляет многие из функций, которые я только что упомянул.

По последним подсчетам, около 1,25 миллиарда поставщиков услуг электронной почты находятся где-то поблизости. Вот некоторые из больших собак:

  • SendGrid — Пожалуй, самый известный поставщик услуг электронной почты. Мы использовали это как плагин Heroku, и интерфейс отлично подходит для изучения вашей электронной почты.
  • Mandrill от MailChimp — предлагает разумную цену с оплатой по мере использования и хороший API. На самом деле мы использовали Postfix (http://www.postfix.org/), настроенный для использования Mandrill, так что у нас нет специальной конфигурации ActionMailer для использования сервиса. Весь конфиг выполняется на Postfix. (Примечание: материал Postfix НЕ обязателен для использования Mandrill)
  • Почтовый штемпель — я никогда не использовал почтовый штемпель, но выглядит он очень интересно. Он добавляет возможность получать электронную почту, преобразовывать ее в JSON и отправлять в приложение Rails.
  • Amazon SES — Сервис простой электронной почты Amazon предлагает почти то же самое, что и предыдущие услуги по очень разумной цене. Я не использовал его, но он в моем списке, просто потому, что это Amazon.
  • Многие, многие другие, такие как Mailjet , SocketLabs и Postage .

Конфигурация этих служб выходит за рамки данной статьи, но если вы серьезно относитесь к электронной почте, вы должны использовать один из них.

Apostle.io Apostle.io предоставляет возможность определять шаблоны электронной почты с помощью их службы. Это удаляет ваши почтовые представления из Rails и помещает их в Apostle.io, чтобы не-Rails разработчики и викинги могли создавать / изменять шаблоны. Он очень просто интегрируется с Rails и большинством сервисов, о которых я упоминал выше.

Общие Gotchas

Все с Rails имеет острый край, который требует от вас максимальной осторожности, и отправка электронной почты ничем не отличается. Вот только пара, но я уверен, что каждый разработчик Rails мог бы добавить один.

У почтовиков нет контекста запроса, как у контроллеров. Этот отсутствующий контекст содержит много информации, но наиболее важным является значение «host». Это значение используется для формирования ссылок. Чтобы это исправить, установите config.action_mailer.default_url_options = {host: 'vikings.com'} или передайте его помощнику url_for . Вы можете использовать only_path для генерации относительных URL, но это бесполезно для электронной почты. Аналогично, все помощники _path url будут бесполезны в электронных письмах, поэтому всегда используйте помощники _url

Следующий посвящен тестированию ваших писем. Я не думаю, что очень многие люди делают это, и это все равно, что есть спам без проверки срока годности. Это действительно позор, потому что тестирование почтовой программы довольно простое. Фактически, у Руководств есть целый раздел, посвященный этому . Этот пример из этого раздела:

 class UserMailerTest < ActionMailer::TestCase test "invite" do # Send the email, then test that it got queued email = UserMailer.create_invite('[email protected]', '[email protected]', Time.now).deliver assert_not ActionMailer::Base.deliveries.empty? # Test the body of the sent email contains what we expect it to assert_equal ['[email protected]'], email.from assert_equal ['[email protected]'], email.to assert_equal 'You have been invited by [email protected]', email.subject assert_equal read_fixture('invite').join, email.body.to_s end end 

Теперь, если вы испытываете затруднения при тестировании нескольких вещей в одном тесте или по любой другой стилистической проблеме, дело в том, что тестирование почтовой программы похоже на тестирование контроллера. Сделай это.

В Rails 4.1 добавлен предварительный просмотр ActionMailer, что позволяет легко и быстро проверять вашу электронную почту. Когда вы генерируете почтовик с Rails 4.1 или выше, он создает файл «предварительного просмотра» в тестовом каталоге. Этот файл предварительного просмотра позволяет вам (предварительный просмотр) просмотреть различные почтовые методы для почтовой программы. Вот пример в руководствах .

Я не использовал превью ActionMailer за исключением краткого ознакомления с ними. Предварительные просмотры ActionMailer не позволяют вам изменять получателя или другие переменные в почтовой программе, поэтому вы должны жестко их кодировать. У меня есть другие предпочтительные варианты, чтобы посмотреть, как выглядят мои письма. Здесь, позвольте мне показать вам …

Драгоценные камни

Есть много, много драгоценных камней, которые делают разные вещи с Rails и почтой. Вот два моих любимых:

  • Перехватчик получателей — обеспечивает простой перехватчик для изменения получателей всех сообщений электронной почты, отправляемых вашим приложением, на один или несколько указанных вами адресов электронной почты. Это классический пример изменения промежуточной среды для отправки электронных писем в команду тестирования для проверки, как я уже упоминал выше. Вы также можете добавить префикс темы (например, [STAGING] ). Взгляните на код, чтобы увидеть, как просто создать перехватчик.
  • Mailcatcher — Mailcatcher создает простой SMTP-сервер, который перехватывает все электронные письма, отправленные вашим приложением Rails, и предоставляет веб-интерфейс для их просмотра. Я использовал MailCatcher целую вечность и мне очень нравится. По моему скромному мнению, это гораздо лучший вариант, чем ActionMailer Previews.

Подписание

Теперь вы знаете все об отправке почты с помощью Rails. Этот пост мог продолжаться вечно, поэтому я попытался смешать некоторые основы и некоторые биты следующего уровня. Я думаю, некоторые из вас говорят такие вещи, как:

  • «Почему он не накрыл Х ???»
  • «О, он совершенно неправ насчет Y !!»
  • «Он действительно ест спам?»

Если да, оставьте эти мысли в комментариях, и я отправлю вам свои ответы по электронной почте.