Ruby on Rails
ActionMailer
Recherche…
Introduction
Action Mailer vous permet d'envoyer des e-mails depuis votre application à l'aide de classes et de vues de courrier. Les publiposteurs fonctionnent de manière très similaire aux contrôleurs. Ils héritent d'ActionMailer :: Base et vivent dans les applications / les courriers, et ils ont des vues associées qui apparaissent dans les applications / vues.
Remarques
Il est conseillé de traiter l'envoi de courrier électronique de manière asynchrone afin de ne pas bloquer votre serveur Web. Cela peut être fait par le biais de divers services tels que delayed_job
.
Basic Mailer
Cet exemple utilise quatre fichiers différents:
- Le modèle d'utilisateur
- Le mailer de l'utilisateur
- Le modèle HTML pour l'e-mail
- Le modèle en texte brut pour l'e-mail
Dans ce cas, le modèle utilisateur appelle la méthode approved
dans l'expéditeur et transmet le post
approuvé (la méthode approved
dans le modèle peut être appelée par un rappel, par une méthode de contrôleur, etc.). Ensuite, l'expéditeur génère l'e-mail à partir du modèle HTML ou texte brut en utilisant les informations du post
transmis (par exemple, le titre). Par défaut, le publiposteur utilise le modèle avec le même nom que la méthode dans le mailer (c'est pourquoi le nom du mailer et les modèles ont le même nom).
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!
Générer un nouveau mailer
Pour générer un nouveau mailer, entrez la commande suivante
rails generate mailer PostMailer
Cela va générer un fichier de modèle vierge dans app/mailers/post_mailer.rb
nommé PostMailer
class PostMailer < ApplicationMailer
end
Deux fichiers de mise en page seront également générés pour la vue email, un pour le format html et un pour le format texte.
Si vous préférez ne pas utiliser le générateur, vous pouvez créer vos propres mailers. Assurez-vous qu'ils héritent d' ActionMailer::Base
Ajout de pièces jointes
ActionMailer
permet également de joindre des fichiers.
attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
Par défaut, les pièces jointes seront encodées avec Base64
. Pour changer cela, vous pouvez ajouter un hachage à la méthode des pièces jointes.
attachments['filename.jpg'] = {
mime_type: 'application/gzip',
encoding: 'SpecialEncoding',
content: encoded_content
}
Vous pouvez également ajouter des pièces jointes en ligne
attachments.inline['image.jpg'] = File.read('/path/to/image.jpg')
ActionMailer Callbacks
ActionMailer prend en charge trois rappels
- avant_action
- après_action
- around_action
Fournissez-les dans votre classe Mailer
class UserMailer < ApplicationMailer
after_action :set_delivery_options, :prevent_delivery_to_guests, :set_business_headers
Ensuite, créez ces méthodes sous le mot-clé private
private
def set_delivery_options
end
def prevent_delivery_to_guests
end
def set_business_headers
end
end
Générer une newsletter programmée
Créez le modèle de newsletter :
rails g model Newsletter name:string email:string subl app/models/newsletter.rb validates :name, presence: true validates :email, presence: true
Créer le contrôleur de 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
Après cela, changez la vue create.html.erb pour le nom nex. Nous allons convertir ce fichier en vue partielle qui sera stockée dans le pied de page . Le nom sera _form.html.erb .
Changer le fichier de nom de: | À: |
---|---|
app / views / newsletters / create.html.erb | app / views / newsletters / _form.html.erb |
Après cela, définissez les itinéraires:
subl app/config/routes.rb resources :newsletters
Plus tard, nous devons définir le formulaire que nous utiliserons pour enregistrer chaque courrier:
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 %>
Et après cela, insérer sur le pied de page:
subl app/views/layouts/_footer.html.erb <%= render 'newsletters/form' %>
Maintenant, installez le - letter_opener - to peut prévisualiser le courrier électronique dans le navigateur par défaut au lieu de l'envoyer. Cela signifie que vous n'avez pas besoin de configurer la remise des e-mails dans votre environnement de développement et que vous n'avez plus besoin d'envoyer accidentellement un e-mail de test à l'adresse de quelqu'un d'autre.
Ajoutez d'abord la gemme à votre environnement de développement et exécutez la commande bundle pour l'installer.
subl your_project/Gemfile gem "letter_opener", :group => :development
Ensuite, définissez la méthode de livraison dans l'environnement de développement:
subl your_project/app/config/environments/development.rb config.action_mailer.delivery_method = :letter_opener
Maintenant, créez une structure de mailer pour gérer l'ensemble des mailers que nous allons travailler. Dans le terminal
rails generate mailer UserMailer newsletter_mailer
Et dans le UserMailer , nous devons créer une méthode appelée Newsletter Mailer qui sera créée pour contenir le dernier article du blog et sera déclenchée par une action de rake. Nous supposerons que vous aviez une structure de blog créée auparavant.
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
Après cela, créez le modèle de 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>
Puisque nous voulons envoyer le courrier électronique en tant que processus distinct, créons une tâche Rake pour envoyer le courrier électronique. Ajoutez un nouveau fichier appelé email_tasks.rake au répertoire lib / tasks de votre application Rails:
touch lib/taks/email_tasks.rake desc 'weekly newsletter email' task weekly_newsletter_email: :environment do UserMailer.newsletter_mailer.deliver! end
L'environnement send_digest_email:: signifie charger l'environnement Rails avant d'exécuter la tâche, vous pouvez donc accéder aux classes d'application (comme UserMailer) dans la tâche.
A présent, l'exécution de la commande rake -T listera la tâche Rake nouvellement créée. Tout tester fonctionne en exécutant la tâche et en vérifiant si l'e-mail est envoyé ou non.
Pour tester si la méthode mailer fonctionne, exécutez la commande rake:
rake weekly_newsletter_email
À ce stade, nous avons une tâche de rake qui peut être programmée en utilisant crontab . Nous allons donc installer le Gemme Whenever qui est utilisé pour fournir une syntaxe claire pour écrire et déployer des tâches cron.
subl your_project/Gemfile gem 'whenever', require: false
Ensuite, exécutez la commande suivante pour créer un fichier config / schedule.rb initial pour vous (tant que le dossier de configuration est déjà présent dans votre projet).
wheneverize . [add] writing `./config/schedule.rb' [done] wheneverized!
Maintenant, à l'intérieur du fichier de programme, nous devons créer notre JOB CRON et appeler la méthode mailer pour déterminer le JOB CRON afin d'exécuter certaines tâches sans assistance et dans une plage de temps sélectionnée. Vous pouvez utiliser différents types de syntaxe, comme expliqué sur ce lien .
subl your_project/config/schedule.rb every 1.day, :at => '4:30 am' do rake 'weekly_newsletter_email' end
Maintenant, pour tester que le Job Cron a été créé avec succès, nous pouvons utiliser la commande suivante pour lire depuis le terminal, notre travail planifié dans 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'
Maintenant, pour exécuter le test dans l'environnement de développement, il est judicieux de définir la ligne suivante du fichier principal application.rb pour que l'application sache où sont les modèles qu'elle utilisera.
subl your_project/config/application.rb config.action_mailer.default_url_options = { :host => "http://localhost:3000/" }
Maintenant, pour laisser Capistrano V3 enregistrer le nouveau Job Cron à l’intérieur du serveur et le déclencheur qui va déclencher l’exécution de cette tâche, nous devons ajouter la condition suivante:
subl your_project/Capfile require 'whenever/capistrano'
Et insérez dans le fichier de déploiement l'identifiant que CRON JOB utilisera sur l' environnement et le nom de l' application .
subl your_project/config/deploy.rb set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:rails_env)}" }
Et prêt, après avoir enregistré les modifications sur chaque fichier, lancez la commande capistrano deploy:
cap production deploy
Et maintenant votre JOB a été créé et calendarize pour exécuter la méthode Mailer qui est ce que je veux et dans la plage de temps que nous définissons sur ces fichiers.
Intercepteur ActionMailer
Action Mailer fournit des points d'ancrage aux méthodes d'intercepteur. Celles-ci vous permettent d'enregistrer les classes appelées pendant le cycle de vie de la distribution du courrier.
Une classe d'intercepteur doit implémenter la méthode: deliver_email (message) qui sera appelée avant l'envoi du courrier électronique, vous permettant de modifier le courrier électronique avant qu'il ne touche les agents de distribution. Votre classe doit apporter les modifications nécessaires directement à l'instance transmise dans Mail :: Message.
Il peut être utile que les développeurs envoient des e-mails à eux-mêmes et non à de vrais utilisateurs.
Exemple d'enregistrement d'un intercepteur 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