Ruby on Rails
ActionMailer
Ricerca…
introduzione
Action Mailer ti consente di inviare e-mail dalla tua applicazione utilizzando le classi e le viste del mailer. I mailer funzionano in modo molto simile ai controller. Essi ereditano da ActionMailer :: Base e vivono in app / mailer e hanno viste associate che appaiono in app / view.
Osservazioni
Si consiglia di elaborare l'invio di e-mail in modo asincrono in modo da non legare il server web. Questo può essere fatto attraverso vari servizi come delayed_job
.
Mailer di base
Questo esempio utilizza quattro file diversi:
- Il modello utente
- Il mailer dell'utente
- Il modello html per l'email
- Il modello di testo semplice per l'email
In questo caso, il modello utente chiama il metodo approved
nel mailer e passa il post
che è stato approvato (il metodo approved
nel modello può essere richiamato da un callback, da un metodo controller, ecc.). Quindi, il mailer genera l'email dal modello html o dal testo normale utilizzando le informazioni del post
passato (ad esempio il titolo). Per impostazione predefinita, il mailer utilizza il modello con lo stesso nome del metodo nel mailer (motivo per cui sia il metodo mailer che i modelli hanno il nome "approvato").
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!
Generare un nuovo mailer
Per generare un nuovo mailer, immettere il seguente comando
rails generate mailer PostMailer
Questo genererà un file modello vuoto in app/mailers/post_mailer.rb
chiamato PostMailer
class PostMailer < ApplicationMailer
end
Verranno inoltre generati due file di layout per la vista e-mail, uno per il formato html e uno per il formato testo.
Se si preferisce non utilizzare il generatore, è possibile creare i propri mailer. Assicurati che ereditino da ActionMailer::Base
Aggiunta di allegati
ActionMailer
consente anche di allegare file.
attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
Per impostazione predefinita, gli allegati saranno codificati con Base64
. Per cambiare questo, puoi aggiungere un hash al metodo degli allegati.
attachments['filename.jpg'] = {
mime_type: 'application/gzip',
encoding: 'SpecialEncoding',
content: encoded_content
}
Puoi anche aggiungere allegati in linea
attachments.inline['image.jpg'] = File.read('/path/to/image.jpg')
Callback di ActionMailer
ActionMailer supporta tre callback
- before_action
- after_action
- around_action
Forniscili nella tua classe Mailer
class UserMailer < ApplicationMailer
after_action :set_delivery_options, :prevent_delivery_to_guests, :set_business_headers
Quindi creare questi metodi sotto la parola chiave private
private
def set_delivery_options
end
def prevent_delivery_to_guests
end
def set_business_headers
end
end
Generare una Newsletter pianificata
Crea il modello di newsletter :
rails g model Newsletter name:string email:string subl app/models/newsletter.rb validates :name, presence: true validates :email, presence: true
Crea il controller della newsletter :
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
Dopodiché, modifica la vista create.html.erb sul nome nex. Convertiremo questo file e la vista parziale che verrà memorizzata all'interno del piè di pagina . Il nome sarà _form.html.erb .
Cambia il nome del file da: | A: |
---|---|
app / views / newsletters / create.html.erb | app / views / newsletters / _form.html.erb |
Successivamente, imposta i percorsi:
subl app/config/routes.rb resources :newsletters
In seguito, dobbiamo impostare il modulo che useremo per salvare ogni mail:
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 %>
E dopo, inserisci sul footer:
subl app/views/layouts/_footer.html.erb <%= render 'newsletters/form' %>
Ora, installa - letter_opener - per poter visualizzare l'anteprima dell'email nel browser predefinito invece di inviarlo. Ciò significa che non è necessario impostare la consegna delle e-mail nel proprio ambiente di sviluppo e non è più necessario preoccuparsi di inviare accidentalmente una e-mail di prova all'indirizzo di qualcun altro.
Per prima cosa aggiungi la gemma al tuo ambiente di sviluppo ed esegui il comando bundle per installarlo.
subl your_project/Gemfile gem "letter_opener", :group => :development
Quindi imposta il metodo di consegna nell'ambiente di sviluppo:
subl your_project/app/config/environments/development.rb config.action_mailer.delivery_method = :letter_opener
Ora, crea una struttura Mailer per gestire gli interi mailer che lavoreremo. Nel terminale
rails generate mailer UserMailer newsletter_mailer
E all'interno dell'UtenteMailer , dobbiamo creare un metodo chiamato Newsletter Mailer che verrà creato per contenere all'interno l'ultimo post del blog e verrà attivato con un'azione di rake. Assumeremo che tu avessi una struttura del blog creata prima.
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
Successivamente, crea il modello di posta elettronica :
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>
Poiché desideriamo inviare l'email come processo separato, creiamo un'attività Rake per attivare l'email. Aggiungi un nuovo file chiamato email_tasks.rake alla directory lib / tasks dell'applicazione 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:: environment significa caricare l'ambiente Rails prima di eseguire l'attività, in modo da poter accedere alle classi dell'applicazione (come UserMailer) all'interno dell'attività.
Ora, eseguendo il comando rake -T verrà elencata l'attività Rake appena creata. Prova tutto funziona eseguendo l'attività e controllando se l'e-mail è stata inviata o meno.
Per verificare se il metodo mailer funziona, eseguire il comando rake:
rake weekly_newsletter_email
A questo punto, abbiamo un'attività di rake di lavoro che può essere pianificata usando crontab . Quindi installeremo il Whenever Gem che viene utilizzato per fornire una sintassi chiara per la scrittura e la distribuzione di cron jobs.
subl your_project/Gemfile gem 'whenever', require: false
Successivamente, esegui il comando successivo per creare un file config / schedule.rb iniziale per te (purché la cartella di configurazione sia già presente nel tuo progetto).
wheneverize . [add] writing `./config/schedule.rb' [done] wheneverized!
Ora, all'interno del file di pianificazione, dobbiamo creare il nostro CRON JOB e chiamare il metodo mailer nel determinare il LAVORO CRON per eseguire alcune attività senza assistenza e in un intervallo di tempo selezionato. È possibile utilizzare diversi tipi di sintassi come spiegato in questo collegamento .
subl your_project/config/schedule.rb every 1.day, :at => '4:30 am' do rake 'weekly_newsletter_email' end
Ora per testare il Cron Job è stato creato con successo possiamo usare il prossimo comando da leggere dal terminale, il nostro lavoro programmato in 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'
Ora, per eseguire il test in Development Environment, è consigliabile impostare la riga successiva sul file principal application.rb per consentire all'applicazione di sapere dove si trovano i modelli che utilizzerà.
subl your_project/config/application.rb config.action_mailer.default_url_options = { :host => "http://localhost:3000/" }
Ora per consentire a Capistrano V3 di salvare il nuovo Cron Job all'interno del server e il trigger che ha attivato l'esecuzione di questa attività, dobbiamo aggiungere il prossimo requisito:
subl your_project/Capfile require 'whenever/capistrano'
E inserire nel file di distribuzione l'identificativo che CRON JOB utilizzerà per l' ambiente e il nome dell'applicazione .
subl your_project/config/deploy.rb set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:rails_env)}" }
E pronto, dopo aver salvato le modifiche su ogni file, esegui il comando capistrano deploy:
cap production deploy
E ora il tuo JOB è stato creato e calendarizzato per eseguire il Metodo Mailer che è quello che voglio e nel tempo che abbiamo impostato su questi file.
ActionMailer Interceptor
Action Mailer fornisce hook nei metodi dell'intercettore. Questi ti consentono di registrare le classi che vengono chiamate durante il ciclo di vita della consegna della posta.
Una classe interceptor deve implementare il metodo: delivering_email (message) che verrà chiamato prima dell'invio dell'e-mail, consentendo di apportare modifiche all'e-mail prima che colpisca gli agenti di consegna. La classe dovrebbe apportare eventuali modifiche necessarie direttamente all'istanza di Mail :: Message passata.
Può essere utile per gli sviluppatori inviare e-mail a se stessi non utenti reali.
Esempio di registrazione di un interceptor di 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