Szukaj…


Wprowadzenie

Action Mailer umożliwia wysyłanie wiadomości e-mail z aplikacji przy użyciu klas i widoków mailera. Mailery działają bardzo podobnie do kontrolerów. Dziedziczą po ActionMailer :: Base i mieszkają w aplikacji / mailerach i mają powiązane widoki, które pojawiają się w aplikacji / widokach.

Uwagi

Wskazane jest przetwarzanie asynchroniczne wysyłania wiadomości e-mail, aby nie wiązać serwera WWW. Można to zrobić za pomocą różnych usług, takich jak delayed_job .

Basic Mailer

W tym przykładzie wykorzystano cztery różne pliki:

  • Model użytkownika
  • Mailer użytkownika
  • Szablon HTML dla wiadomości e-mail
  • Szablon zwykłego tekstu dla wiadomości e-mail

W takim przypadku model użytkownika wywołuje metodę approved w programie post i przekazuje zatwierdzoną wiadomość (metoda approved w modelu może zostać wywołana przez wywołanie zwrotne, z metody kontrolera itp.). Następnie program pocztowy generuje wiadomość e-mail z szablonu HTML lub zwykłego tekstu na podstawie informacji z przekazanego post (np. Tytułu). Domyślnie program pocztowy używa szablonu o tej samej nazwie co metoda w programie pocztowym (dlatego zarówno metoda programu pocztowego, jak i szablony mają nazwę „zatwierdzona”).

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

zatwierdzony.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>

zatwierdzony.tekst.erb

Congrats <%= @user.name %>! Your post (#<%= @title %>) has been approved!
We look forward to your future posts!

Generowanie nowego mailera

Aby wygenerować nowy program pocztowy, wprowadź następujące polecenie

rails generate mailer PostMailer 

Spowoduje to wygenerowanie pustego pliku szablonu w app/mailers/post_mailer.rb o nazwie PostMailer

class PostMailer < ApplicationMailer
end

Zostaną również wygenerowane dwa pliki układu dla widoku e-mail, jeden dla formatu HTML i jeden dla formatu tekstowego.

Jeśli wolisz nie używać generatora, możesz tworzyć własne mailery. Upewnij się, że dziedziczą po ActionMailer::Base

Dodawanie załączników

ActionMailer umożliwia także dołączanie plików.

attachments['filename.jpg'] = File.read('/path/to/filename.jpg')

Domyślnie załączniki będą kodowane przy użyciu Base64 . Aby to zmienić, możesz dodać skrót do metody załączników.

attachments['filename.jpg'] = {
  mime_type: 'application/gzip',
  encoding: 'SpecialEncoding',
  content: encoded_content
}

Możesz także dodawać załączniki wbudowane

attachments.inline['image.jpg'] = File.read('/path/to/image.jpg')

Oddzwanianie ActionMailer

ActionMailer obsługuje trzy połączenia zwrotne

  • przed działaniem
  • następstwo
  • około aktywności

Podaj je w swojej klasie Mailer

class UserMailer < ApplicationMailer
  after_action :set_delivery_options, :prevent_delivery_to_guests, :set_business_headers

Następnie utwórz te metody pod private słowem kluczowym

private
  def set_delivery_options
  end

  def prevent_delivery_to_guests
  end

  def set_business_headers
  end
end

Wygeneruj zaplanowany biuletyn

Utwórz model biuletynu :

  rails g model Newsletter name:string email:string

  subl app/models/newsletter.rb

  validates :name, presence: true
  validates :email, presence: true

Utwórz kontroler biuletynu :

  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

Następnie zmień widok create.html.erb na nazwę nex. Konwertujemy ten plik do częściowego widoku, który będzie przechowywany w stopce . Nazwą będzie _form.html.erb .

Zmień nazwę pliku z: Do:
app / views / newsletters / create.html.erb app / views / newsletters / _form.html.erb

Następnie ustaw trasy:

  subl app/config/routes.rb
    
  resources :newsletters

Później musimy ustawić formularz, w którym będziemy zapisywać każdą pocztę:

  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 %>

A następnie wstaw stopkę:

  subl app/views/layouts/_footer.html.erb

  <%= render 'newsletters/form' %>

Teraz zainstaluj - letter_opener - aby wyświetlić podgląd wiadomości e-mail w domyślnej przeglądarce zamiast jej wysyłać. Oznacza to, że nie musisz konfigurować dostarczania wiadomości e-mail w środowisku programistycznym i nie musisz się już martwić przypadkowym wysłaniem wiadomości e-mail testowej na adres innej osoby.

Najpierw dodaj klejnot do środowiska programistycznego i uruchom polecenie pakietu, aby go zainstalować.

  subl your_project/Gemfile

  gem "letter_opener", :group => :development

Następnie ustaw metodę dostarczania w środowisku programistycznym:

  subl your_project/app/config/environments/development.rb

  config.action_mailer.delivery_method = :letter_opener

Teraz utwórz Strukturę Mailera, aby zarządzać całością mailerów, którymi będziemy pracować. W terminalu

  rails generate mailer UserMailer newsletter_mailer

Wewnątrz UserMailer musimy stworzyć metodę o nazwie Newsletter Mailer, która zostanie utworzona w celu umieszczenia wewnątrz najnowszego posta na blogu i zostanie zwolniona za pomocą akcji rake. Zakładamy, że masz już utworzoną strukturę bloga.

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

Następnie utwórz szablon 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>

Ponieważ chcemy wysłać wiadomość e-mail jako osobny proces, utwórzmy zadanie Rake, aby wysłać wiadomość e-mail. Dodaj nowy plik o nazwie email_tasks.rake do katalogu lib / tasks swojej aplikacji Rails:

touch lib/taks/email_tasks.rake

desc 'weekly newsletter email'
task weekly_newsletter_email: :environment do
  UserMailer.newsletter_mailer.deliver!
end

Środowisko send_digest_email:: oznacza załadowanie środowiska Rails przed uruchomieniem zadania, dzięki czemu można uzyskać dostęp do klas aplikacji (takich jak UserMailer) w ramach zadania.

Teraz uruchomienie polecenia prowizji -T wyświetli listę nowo utworzonego zadania prowizji. Sprawdź, czy wszystko działa, uruchamiając zadanie i sprawdzając, czy wiadomość e-mail została wysłana, czy nie.

Aby sprawdzić, czy metoda mailera działa, uruchom polecenie rake:

  rake weekly_newsletter_email

W tym momencie mamy działające zadanie rake, które można zaplanować za pomocą crontab . Zainstalujemy więc aplikację Ever Ever Gem, która służy do zapewnienia jasnej składni do pisania i wdrażania zadań cron.

subl your_project/Gemfile
  
  gem 'whenever', require: false

Następnie uruchom następną komendę, aby utworzyć dla Ciebie początkowy plik config / schedule.rb (o ile folder konfiguracji jest już obecny w projekcie).

  wheneverize .

  [add] writing `./config/schedule.rb'
  [done] wheneverized!

Teraz, w pliku harmonogramu, musimy utworzyć nasz CRON JOB i wywołać metodę mailer wewnątrz określania CRON JOB, aby wykonać niektóre zadania bez pomocy i w wybranym przedziale czasu. Możesz użyć różnych rodzajów składni, jak wyjaśniono w tym linku .

subl your_project/config/schedule.rb

every 1.day, :at => '4:30 am' do
  rake 'weekly_newsletter_email'
end

Podstawowa składnia zadania Cron

Praca z Cron za każdym razem

Aby przetestować zadanie Cron zostało pomyślnie utworzone, możemy użyć następnego polecenia do odczytu od terminala, naszego zaplanowanego zadania w 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'

Teraz, aby uruchomić test w środowisku programistycznym, rozsądnie jest ustawić następny wiersz w pliku głównym application.rb , aby aplikacja wiedziała, w jakich modelach będzie używać.

  subl your_project/config/application.rb

  config.action_mailer.default_url_options = { :host => "http://localhost:3000/" }

Teraz, aby umożliwić Capistrano V3 zapisanie nowego zadania Cron wewnątrz serwera i wyzwalacza, który uruchomi wykonanie tego zadania, musimy dodać kolejny wymóg:

  subl your_project/Capfile

  require 'whenever/capistrano'

I wstaw do pliku wdrażania identyfikator, którego CRON JOB będzie używał w odniesieniu do środowiska i nazwę aplikacji .

subl your_project/config/deploy.rb

set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:rails_env)}" }

I gotowe, po zapisaniu zmian w każdym pliku, uruchom polecenie wdrażania capistrano:

  cap production deploy

A teraz twoja praca została utworzona i kalendarza, aby uruchomić metodę Mailera, która jest tym, czego chcę i w zakresie czasu, który ustalamy na tych plikach.

ActionMailer Interceptor

Action Mailer zapewnia przechwytywanie metod przechwytujących. Umożliwiają one rejestrację klas wywoływanych podczas cyklu życia dostarczania poczty.

Klasa przechwytująca musi implementować metodę: delivering_email (wiadomość), która zostanie wywołana przed wysłaniem wiadomości e-mail, umożliwiając modyfikację wiadomości e-mail, zanim dotrze ona do agentów dostarczających. Twoja klasa powinna wprowadzić wszelkie potrzebne modyfikacje bezpośrednio w przekazanej instancji Mail :: Message.

Programiści mogą wysyłać wiadomości e-mail do siebie, a nie rzeczywistych użytkowników.

Przykład rejestracji przechwytywacza 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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow