Поиск…


Вступление

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

Работа в Cron

Теперь, чтобы проверить, что 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


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow