Ruby on Rails
ActionMailer
Поиск…
Вступление
Action Mailer позволяет отправлять электронные письма из вашего приложения, используя классы и представления почтовой программы. Mailers работают очень похоже на контроллеры. Они наследуют ActionMailer :: Base и живут в приложениях / почтовых программах, и у них есть связанные представления, которые появляются в приложениях / представлениях.
замечания
Целесообразно обрабатывать отправку электронной почты асинхронно, чтобы не связывать ваш веб-сервер. Это можно сделать с помощью различных сервисов, таких как delayed_job
.
Основной Mailer
В этом примере используются четыре разных файла:
- Модель пользователя
- Пользовательская почтовая программа
- Шаблон html для электронной почты
- Шаблон текстового текста для электронной почты
В этом случае модель пользователя называет approved
метод в post
отправителе и передает утвержденную post
( approved
метод в модели может быть вызван обратным вызовом, методом контроллера и т. Д.). Затем почтовая программа генерирует электронное письмо из шаблона html или plain-text, используя информацию из отправленного post
(например, заголовок). По умолчанию почтовая программа использует шаблон с тем же именем, что и метод в почтовом ящике (поэтому и метод почтовой программы, и шаблоны имеют имя «одобрено»).
user_mailer.rb
class UserMailer < ActionMailer::Base
default from: "[email protected]"
def approved(post)
@title = post.title
@user = post.user
mail(to: @user.email, subject: "Your Post was Approved!")
end
end
user.rb
def approved(post)
UserMailer.approved(post)
end
approved.html.erb
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Post Approved</title>
</head>
<body>
<h2>Congrats <%= @user.name %>! Your post (#<%= @title %>) has been approved!</h2>
<p>We look forward to your future posts!</p>
</body>
</html>
approved.text.erb
Congrats <%= @user.name %>! Your post (#<%= @title %>) has been approved!
We look forward to your future posts!
Создание новой почтовой программы
Чтобы создать новую почтовую программу, введите следующую команду
rails generate mailer PostMailer
Это создаст пустой файл шаблона в app/mailers/post_mailer.rb
именем PostMailer
class PostMailer < ApplicationMailer
end
Для представления электронной почты будут созданы два файла макета, один для формата html и один для текстового формата.
Если вы предпочитаете не использовать генератор, вы можете создать свои собственные почтовые программы. Убедитесь, что они наследуются от ActionMailer::Base
Добавление вложений
ActionMailer
также позволяет прикреплять файлы.
attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
По умолчанию вложения будут закодированы с помощью Base64
. Чтобы изменить это, вы можете добавить хэш к методу вложений.
attachments['filename.jpg'] = {
mime_type: 'application/gzip',
encoding: 'SpecialEncoding',
content: encoded_content
}
Вы также можете добавить встроенные вложения
attachments.inline['image.jpg'] = File.read('/path/to/image.jpg')
Обратные вызовы ActionMailer
ActionMailer поддерживает три обратных вызова
- before_action
- after_action
- around_action
Предоставьте их в своем классе Mailer
class UserMailer < ApplicationMailer
after_action :set_delivery_options, :prevent_delivery_to_guests, :set_business_headers
Затем создайте эти методы под ключевым словом private
private
def set_delivery_options
end
def prevent_delivery_to_guests
end
def set_business_headers
end
end
Создание запланированного информационного бюллетеня
Создайте модель информационного бюллетеня :
rails g model Newsletter name:string email:string subl app/models/newsletter.rb validates :name, presence: true validates :email, presence: true
Создайте контроллер информационного бюллетеня :
rails g controller Newsletters create class NewslettersController < ApplicationController skip_before_action :authenticate_user! before_action :set_newsletter, only: [:destroy] def create @newsletter = Newsletter.create(newsletter_params) if @newsletter.save redirect_to blog_index_path else redirect_to root_path end end private def set_newsletter @newsletter = Newsletter.find(params[:id]) end def newsletter_params params.require(:newsletter).permit(:name, :email) end end
После этого измените представление create.html.erb на имя nex. Мы преобразуем этот файл в частичный просмотр, который будет сохранен в нижнем колонтитуле . Имя будет _form.html.erb .
Измените имя файла: | Для того, чтобы: |
---|---|
app / views / newsletters / create.html.erb | app / views / newsletters / _form.html.erb |
После этого установите маршруты:
subl app/config/routes.rb resources :newsletters
Позже нам нужно установить форму, которую мы будем использовать для сохранения каждой почты:
subl app/views/newsletters/_form.html.erb <%= form_for (Newsletter.new) do |f| %> <div class="col-md-12" style="margin: 0 auto; padding: 0;"> <div class="col-md-6" style="padding: 0;"> <%= f.text_field :name, class: 'form-control', placeholder:'Nombre' %> </div> <div class="col-md-6" style="padding: 0;"> <%= f.text_field :email, class: 'form-control', placeholder:'Email' %> </div> </div> <div class="col-md-12" style="margin: 0 auto; padding:0;"> <%= f.submit class:"col-md-12 tran3s s-color-bg hvr-shutter-out-horizontal", style:'border: none; color: white; cursor: pointer; margin: 0.5em auto; padding: 0.75em; width: 100%;' %> </div> <% end %>
И после этого вставьте нижний колонтитул:
subl app/views/layouts/_footer.html.erb <%= render 'newsletters/form' %>
Теперь установите - letter_opener - чтобы можно было просматривать электронную почту в браузере по умолчанию вместо отправки. Это означает, что вам не нужно настраивать доставку электронной почты в среду разработки, и вам больше не нужно беспокоиться о том, чтобы случайно отправить тестовое письмо на чужой адрес.
Сначала добавьте драгоценный камень в среду разработки и запустите команду bundle, чтобы установить ее.
subl your_project/Gemfile gem "letter_opener", :group => :development
Затем установите способ доставки в среде разработки:
subl your_project/app/config/environments/development.rb config.action_mailer.delivery_method = :letter_opener
Теперь создайте структуру Mailer для управления всеми почтовыми серверами, которые мы будем работать. В терминале
rails generate mailer UserMailer newsletter_mailer
И внутри UserMailer мы должны создать метод под названием Newsletter Mailer, который будет создан, чтобы содержать внутри последнего сообщения блога и будет выпущен с помощью рейк-действий. Предположим, что у вас была структура блога, созданная ранее.
subl your_project/app/mailers/user_mailer.rb class UserMailer '[email protected]' def newsletter_mailer @newsletter = Newsletter.all @post = Post.last(3) emails = @newsletter.collect(&:email).join(", ") mail(to: emails, subject: "Hi, this is a test mail.") end end
После этого создайте шаблон Mailer :
subl your_project/app/views/user_mailer/newsletter_mailer.html.erb <p> Dear Followers: </p> <p> Those are the lastest entries to our blog. We invite you to read and share everything we did on this week. </p> <br/> <table> <% @post.each do |post| %> <%#= link_to blog_url(post) do %> <tr style="display:flex; float:left; clear:both;"> <td style="display:flex; float:left; clear:both; height: 80px; width: 100px;"> <% if post.cover_image.present? %> <%= image_tag post.cover_image.fullsize.url, class:"principal-home-image-slider" %> <%# else %> <%#= image_tag 'http://your_site_project.com' + post.cover_video, class:"principal-home-image-slider" %> <%#= raw(video_embed(post.cover_video)) %> <% end %> </td> <td> <h3> <%= link_to post.title, :controller => "blog", :action => "show", :only_path => false, :id => post.id %> </h3> <p><%= post.subtitle %></p> </td> <td style="display:flex; float:left; clear:both;"> </td> </tr> <%# end %> <% end %> </table>
Поскольку мы хотим отправить электронное письмо как отдельный процесс, давайте создадим задачу Rake, чтобы отключить электронную почту. Добавьте новый файл с именем email_tasks.rake в каталог lib / tasks приложения Rails:
touch lib/taks/email_tasks.rake desc 'weekly newsletter email' task weekly_newsletter_email: :environment do UserMailer.newsletter_mailer.deliver! end
Среда send_digest_email:: означает загрузку среды Rails перед запуском задачи, поэтому вы можете получить доступ к классам приложений (например, UserMailer) внутри задачи.
Теперь выполнение команды rake -T будет отображать вновь созданную задачу Rake. Проверьте все, выполнив задачу и проверив, отправлено ли электронное письмо.
Чтобы проверить, работает ли почтовый метод, выполните команду rake:
rake weekly_newsletter_email
На этом этапе у нас есть рабочая задача, которая может быть запланирована с помощью crontab . Поэтому мы установим Whenever Gem, который используется для обеспечения четкого синтаксиса для написания и развертывания заданий cron.
subl your_project/Gemfile gem 'whenever', require: false
После этого запустите следующую команду, чтобы создать исходный файл config / schedule.rb для вас (если папка конфигурации уже присутствует в вашем проекте).
wheneverize . [add] writing `./config/schedule.rb' [done] wheneverized!
Теперь, внутри файла расписания, мы должны создать нашу CRON JOB и вызвать метод почтовой программы при определении CRON JOB для управления некоторыми задачами без помощи и в выбранный диапазон времени. Вы можете использовать разные типы синтаксиса, как описано в этой ссылке .
subl your_project/config/schedule.rb every 1.day, :at => '4:30 am' do rake 'weekly_newsletter_email' end
Теперь, чтобы проверить, что Cron Job был успешно создан, мы можем использовать следующую команду для чтения с терминала, нашу запланированную работу в CRON SYNTAX:
your_project your_mac_user$ whenever 30 4 * * * /bin/bash -l -c 'cd /Users/your_mac_user/Desktop/your_project && RAILS_ENV=production bundle exec rake weekly_newsletter_email --silent'
Теперь, чтобы запустить тест в среде разработки, целесообразно установить следующую строку в главном файле application.rb, чтобы приложение могло узнать, какие модели они будут использовать.
subl your_project/config/application.rb config.action_mailer.default_url_options = { :host => "http://localhost:3000/" }
Теперь, чтобы Capistrano V3 сохранил новое задание Cron внутри сервера и триггер, который запустил выполнение этой задачи, мы должны добавить следующее требование:
subl your_project/Capfile require 'whenever/capistrano'
И вставьте в файл развертывания идентификатор, который CRON JOB будет использовать об окружающей среде и имя приложения .
subl your_project/config/deploy.rb set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:rails_env)}" }
И, после сохранения изменений в каждом файле, запустите команду развертывания capistrano:
cap production deploy
И теперь ваша JOB была создана и календарна для запуска метода Mailer, который я хочу, и в течение времени, которое мы установили в этих файлах.
Перехватчик ActionMailer
Action Mailer предоставляет перехватчики в методах перехватчика. Это позволяет вам регистрировать классы, которые вызывают во время цикла доставки почты.
Класс перехватчика должен реализовать метод: delivering_email (message), который будет вызываться до отправки электронной почты, что позволит вам вносить изменения в электронную почту до того, как она попадет в агенты доставки. Ваш класс должен внести любые необходимые изменения непосредственно в переданный экземпляр Mail :: Message.
Разработчикам может быть полезно отправить электронную почту самим себе не настоящим пользователям.
Пример регистрации перехватчика actionmailer:
# config/initializers/override_mail_recipient.rb
if Rails.env.development? or Rails.env.test?
class OverrideMailRecipient
def self.delivering_email(mail)
mail.subject = 'This is dummy subject'
mail.bcc = '[email protected]'
mail.to = '[email protected]'
end
end
ActionMailer::Base.register_interceptor(OverrideMailRecipient)
end