Ruby on Rails
ActionMailer
Zoeken…
Invoering
Met Action Mailer kunt u e-mails verzenden vanuit uw toepassing met behulp van mailerklassen en views. Mailers werken op dezelfde manier als controllers. Ze erven van ActionMailer :: Base en wonen in app / mailers, en ze hebben bijbehorende weergaven die in app / weergaven verschijnen.
Opmerkingen
Het is raadzaam om het verzenden van e-mail asynchroon te verwerken om uw webserver niet vast te zetten. Dit kan via verschillende services, zoals delayed_job
.
Basic Mailer
Dit voorbeeld gebruikt vier verschillende bestanden:
- Het gebruikersmodel
- De gebruikersmailer
- De HTML-sjabloon voor de e-mail
- De platte tekstsjabloon voor de e-mail
In dit geval roept het gebruikersmodel de approved
methode in de mailer aan en geeft deze de goedgekeurde post
(de approved
methode in het model kan worden opgeroepen door een callback, een controller-methode, enz.). Vervolgens genereert de mailer de e-mail uit de HTML- of platte tekstsjabloon met behulp van de informatie uit het doorgegeven post
(bijvoorbeeld de titel). Standaard gebruikt de mailer de sjabloon met dezelfde naam als de methode in de mailer (vandaar dat zowel de mailer-methode als de sjablonen de naam 'goedgekeurd' hebben).
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!
Een nieuwe mailer genereren
Voer de volgende opdracht in om een nieuwe mailer te genereren
rails generate mailer PostMailer
Dit genereert een leeg sjabloonbestand in app/mailers/post_mailer.rb
naam PostMailer
class PostMailer < ApplicationMailer
end
Er worden ook twee lay-outbestanden gegenereerd voor de e-mailweergave, een voor de html-indeling en een voor de tekstindeling.
Als u de generator liever niet gebruikt, kunt u uw eigen mailers maken. Zorg ervoor dat ze erven van ActionMailer::Base
Bijlagen toevoegen
ActionMailer
maakt het ook mogelijk om bestanden toe te ActionMailer
.
attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
Bijlagen worden standaard gecodeerd met Base64
. Om dit te wijzigen, kunt u een hash toevoegen aan de bijlagenmethode.
attachments['filename.jpg'] = {
mime_type: 'application/gzip',
encoding: 'SpecialEncoding',
content: encoded_content
}
U kunt ook inline bijlagen toevoegen
attachments.inline['image.jpg'] = File.read('/path/to/image.jpg')
ActionMailer Callbacks
ActionMailer ondersteunt drie callbacks
- before_action
- after_action
- around_action
Lever deze in uw Mailer-klasse
class UserMailer < ApplicationMailer
after_action :set_delivery_options, :prevent_delivery_to_guests, :set_business_headers
Maak vervolgens deze methoden onder het private
trefwoord
private
def set_delivery_options
end
def prevent_delivery_to_guests
end
def set_business_headers
end
end
Genereer een geplande nieuwsbrief
Maak het nieuwsbriefmodel :
rails g model Newsletter name:string email:string subl app/models/newsletter.rb validates :name, presence: true validates :email, presence: true
Maak de nieuwsbriefcontroller :
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
Wijzig daarna de weergave create.html.erb in de naam nex. We zullen dit bestand converteren naar een gedeeltelijke weergave die wordt opgeslagen in de voettekst . De naam zal _form.html.erb zijn .
Naambestand wijzigen van: | Naar: |
---|---|
app / views / nieuwsbrieven / create.html.erb | app / views / nieuwsbrieven / _form.html.erb |
Stel daarna de routes in:
subl app/config/routes.rb resources :newsletters
Later moeten we het formulier instellen dat we gebruiken om elke e-mail op te slaan:
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 %>
En daarna op de voettekst invoegen:
subl app/views/layouts/_footer.html.erb <%= render 'newsletters/form' %>
Installeer nu de - letter_opener - om een voorbeeld van e-mail te bekijken in de standaardbrowser in plaats van deze te verzenden. Dit betekent dat u geen e-mailbezorging hoeft in te stellen in uw ontwikkelomgeving en dat u zich geen zorgen meer hoeft te maken dat u per ongeluk een test-e-mail naar het adres van iemand anders verzendt.
Voeg eerst de edelsteen toe aan uw ontwikkelomgeving en voer de bundelopdracht uit om deze te installeren.
subl your_project/Gemfile gem "letter_opener", :group => :development
Stel vervolgens de leveringsmethode in de ontwikkelomgeving in:
subl your_project/app/config/environments/development.rb config.action_mailer.delivery_method = :letter_opener
Maak nu een Mailer-structuur om alle mailers te beheren waaraan we zullen werken. In terminal
rails generate mailer UserMailer newsletter_mailer
En in de UserMailer moeten we een methode genaamd Nieuwsbrief Mailer maken die zal worden gemaakt om in de laatste blogpost te worden opgenomen en met een rake-actie wordt ontslagen. We gaan ervan uit dat je eerder een blogstructuur hebt gemaakt.
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
Maak daarna de sjabloon 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>
Omdat we de e-mail als een afzonderlijk proces willen verzenden, laten we een harktaak maken om de e-mail af te vuren. Voeg een nieuw bestand met de naam email_tasks.rake toe aan de map lib / taken van uw Rails-toepassing:
touch lib/taks/email_tasks.rake desc 'weekly newsletter email' task weekly_newsletter_email: :environment do UserMailer.newsletter_mailer.deliver! end
De send_digest_email:: omgeving betekent dat de Rails-omgeving wordt geladen voordat de taak wordt uitgevoerd, zodat u toegang hebt tot de toepassingsklassen (zoals UserMailer) binnen de taak.
Als u nu de opdracht rake -T uitvoert, wordt de nieuw gemaakte harktaak weergegeven. Test alles werkt door de taak uit te voeren en te controleren of de e-mail is verzonden of niet.
Voer de opdracht rake uit om te testen of de mailer-methode werkt:
rake weekly_newsletter_email
Op dit moment hebben we een werkende harktaak die kan worden gepland met crontab . Daarom zullen we de Whenever Gem installeren die wordt gebruikt om een duidelijke syntaxis te bieden voor het schrijven en implementeren van cron-taken.
subl your_project/Gemfile gem 'whenever', require: false
Voer daarna de volgende opdracht uit om een eerste config / schedule.rb-bestand voor u te maken (zolang de map config al in uw project aanwezig is).
wheneverize . [add] writing `./config/schedule.rb' [done] wheneverized!
Nu, binnen het planningsbestand, moeten we onze CRON JOB aanmaken en de mailer-methode oproepen om de CRON JOB te bepalen om bepaalde taken zonder hulp en binnen een bepaald tijdsbereik uit te voeren. U kunt verschillende soorten syntaxis gebruiken, zoals wordt uitgelegd op deze link .
subl your_project/config/schedule.rb every 1.day, :at => '4:30 am' do rake 'weekly_newsletter_email' end
Nu om te testen of de Cron Job succesvol is gemaakt, kunnen we de volgende opdracht gebruiken om te lezen sinds terminal, onze geplande taak 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'
Om de test in de ontwikkelomgeving uit te voeren, is het verstandig om de volgende regel in het hoofdbestand van de application.rb in te stellen om de toepassing te laten weten waar de modellen zijn die worden gebruikt.
subl your_project/config/application.rb config.action_mailer.default_url_options = { :host => "http://localhost:3000/" }
Om Capistrano V3 de nieuwe Cron Job binnen de server en de trigger te laten opslaan die de uitvoering van deze taak zal starten, moeten we de volgende vereiste toevoegen:
subl your_project/Capfile require 'whenever/capistrano'
En voeg in het deploy- bestand de identifier in die CRON JOB zal gebruiken over de omgeving en de naam van de applicatie .
subl your_project/config/deploy.rb set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:rails_env)}" }
En klaar, na het opslaan van wijzigingen in elk bestand, voert u de opdracht capistrano deploy uit:
cap production deploy
En nu is je JOB gemaakt en in een agenda geplaatst om de Mailer-methode uit te voeren, wat ik wil en binnen de tijdsperiode die we voor deze bestanden instellen.
ActionMailer Interceptor
Action Mailer biedt haken in de interceptormethoden. Hiermee kunt u klassen registreren die worden aangeroepen tijdens de levenscyclus van e-mailbezorging.
Een interceptorklasse moet de methode: deliver_email (bericht) implementeren die wordt aangeroepen voordat de e-mail wordt verzonden, zodat u de e-mail kunt wijzigen voordat deze de bezorgers raakt. Uw klas moet de benodigde wijzigingen rechtstreeks in het exemplaar in Mail :: Message aanbrengen.
Het kan handig zijn voor ontwikkelaars om e-mail naar zichzelf te sturen, niet naar echte gebruikers.
Voorbeeld van het registreren van een Actionmailer-interceptor:
# 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