E-Mail senden

E-Mail senden

Dank Action Mailer ist das Versenden von E-Mails in Rails einfach, aber es gibt einige Fallstricke, auf die man achten sollte. Hier zeige ich, wie man nach dem Absenden eines Formulars eine E-Mail versendet, und welche Konfigurationsoptionen erforderlich sind.

Rails App mailit

Das Versenden von E-Mails aus Rails-Anwendungen ist dank ActionMailer einfach, aber es gibt einige Probleme, auf die wir stoßen können. In dieser Episode zeigen wir, wie es funktioniert, und wie man einige gängige Probleme vermeidet. Zur Veranschaulichung verwenden wir eine einfache Anwendung mit Feldern für Namen und E-Mail-Adressen (um dieses Beispiel einfach zu halten, gibt es keine üblichen Passwortfelder).
$ rails new mailit
$ cd mailit
$ rails g scaffold User name email
$ rails db:migrate
Ein gem installieren.
// Gemfile

gem 'sassc-rails'
Jetzt noch einbinden.
$ bundle install

1.png 688 KB

Ein Mailer erstellen

$ rails g mailer user_mailer signup_confirmation
Diese Befehl erstellt ein Verzeichnis app/mailers mit einer Datei user_mailer.rb darin, und wir können dies verwenden, um unsere Anmeldebestätigungs-E-Mail zu versenden. Der Generator erstellt auch eine Ansicht für die Nachricht, die standardmäßigen Text enthält.
// app/views/user_mailer/signup_confirmation.text.erb

UserMailer#signup_confirmation

<%= @greeting %>, find me in app/views/app/views/user_mailer/signup_confirmation.text.erb
Bitte beachten Sie, dass wir Instanzvariablen zwischen der Ansicht und dem Mailer genauso teilen können wie mit einem Controller.

Es ist wichtig, dass die signup_confirmation-Methode mit einem Aufruf von mail endet, da dies die E-Mail generiert und zurückgibt. Wir können verschiedenen Optionen an diese Methode übergeben, einschließlich des Empfängers und des Betreffs der Nachricht. Ein Kommentar oben in der Klasse zeigt uns, dass wir den Betreff auch in der Internationalisierungsdatei festlegen können, aber wir setzen ihn direkt hier, da wir keine Unterstützung für mehrere Sprachen benötigen.
// app/mailers/user_mailer.rb

class UserMailer < ApplicationMailer

  # Subject can be set in your I18n file at config/locales/en.yml
  # with the following lookup:
  #
  #   en.user_mailer.signup_confirmation.subject
  #
  def signup_confirmation
    @greeting = "Hi"

    mail to: "to@example.org"
  end
end
Die API-Dokumentation zeigt uns eine Liste aller Optionen, die wir an die mail-Methode übergeben können.

Wenn wir mehrere Methoden in einer Mailer-Klasse definiert haben und Optionen zwischen ihnen teilen möchten, können wir einen Aufruf an default machen. Alle hier definierten Optionen werden automatisch auf jeden Aufruf von mail angewendet. Wir werden es verwenden, um festzulegen, von wem die E-Mails gesendet werden sollen.
// app/mailers/application_mailer.rb

default from: "no-replay@b4um.com"
Wir müssen immer noch angeben, an wen die E-Mail gesendet werden soll; dies sollte die E-Mail sein, die im Formular angegeben ist. Nach Design haben Mailer-Klassen keinen Zugriff auf Anforderungsparameter, daher müssen wir das User-Modell auf andere Weise übergeben. Wir werden die signup_confirmation-Methode ändern, damit sie ein Benutzerargument akzeptiert, und den Benutzer auf diese Weise übergeben. Dann können wir user.email aufrufen, um ihre E-Mail-Adresse zu erhalten. Wir setzen auch eine Instanzvariable auf diesen Benutzer, damit wir sie in der Ansicht verwenden können.
// app/mailers/user_mailer.rb
def signup_confirmation(user)
  @user = user

  mail to: user.email, subject: 'Sign Up Confirmation'
end
Wir können diese Instanzvariable in der Ansicht verwenden, um den Namen des Benutzers in der E-Mail hinzuzufügen.
// app/views/user_mailer/signup_confirmation.text.erb

<%= @user.name %>,

Thank you for signing up.
Unsere E-Mail ist jetzt weitgehend fertig, und wir müssen sie nur noch aus unserem Controller versenden. Wir könnten die E-Mail über einen Model-Observer oder einen Callback senden, aber wir senden die E-Mail im Controller, damit wir keine E-Mails unbeabsichtigt senden, wenn wir auf andere Weise mit dem Modell interagieren.
// app/controllers/users_controller.rb

def create
  @user = User.new(user_params)

  respond_to do |format|
    if @user.save
      UserMailer.signup_confirmation(@user).deliver_now
      format.html { redirect_to user_url(@user), notice: "User was successfully created." }
      format.json { render :show, status: :created, location: @user }
    else
      format.html { render :new, status: :unprocessable_entity }
      format.json { render json: @user.errors, status: :unprocessable_entity }
    end
  end
end
Um die E-Mail zu senden, rufen wir UserMailer.signup_confirmation auf, übergeben unseren Benutzer und rufen deliver_now darauf auf. Sie haben möglicherweise bemerkt, dass wir signup_confirmation als Klassenmethode aufrufen, während es in der UserMailer-Klasse eine Instanzmethode ist. Wie funktioniert das? Die Antwort liegt im Rails-Quellcode für ActionMailer. Dieser verwendet method_missing, um eine neue Instanz des Mailers zu erstellen und die fehlende Methode darauf aufzurufen.

Wir können dies jetzt ausprobieren. Nachdem wir den Server neu gestartet haben, um die Änderungen zu übernehmen, werden wir das Formular absenden und prüfen, ob die E-Mail gesendet wird. Es scheint jedoch nicht zu funktionieren, und standardmäßig ignoriert Rails Fehler stillschweigend, die beim Versuch, E-Mails zu senden, auftreten. Das macht das Debuggen dieses Problems schwierig. Um es einfacher zu machen, können wir die Entwicklungs-Konfigurationsdatei ändern und raise_delivery_errors auf true setzen.
// config/environments/development.rb

# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = true
Eine Ausnahme wird jetzt ausgelöst, wenn das Senden einer E-Mail fehlschlägt. Nach dem Neustart des Servers und dem erneuten Absenden des Formulars erhalten wir diesmal eine "Connection refused"-Ausnahme. Auch diese Fehlermeldung ist nicht besonders hilfreich, bedeutet jedoch im Wesentlichen, dass Rails keine Verbindung zum SMTP-Server herstellen kann, der standardmäßig als localhost festgelegt ist. Wir können ändern, wie E-Mails gesendet werden, indem wir die delivery_method festlegen. Diese können wir auf smtp, sendmail, file oder test setzen.
// config/environments/development.rb

config.action_mailer.delivery_method = :smtp
Wenn wir einen anderen Server verwenden möchten, können wir die Einstellung smtp_settings wie folgt in einer neuen Datei, die wir noch erstellen müssen, festlegen:
// config/initializers/setup_mail.rb

require 'action_mailer'

ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
  address: 'smtp.gmail.de',
  port: 587,
  authentication: :login,
  user_name: ENV['SUEDSEE_USER_NAME'],
  password: ENV['SUEDSEE_PASSWORD'],
  ssl: true
}

ActionMailer::Base.default_url_options[:host] = 'www.b4um.com'
Natürlich müssen Sie Ihre eigenen Benutzernamen- und Kennworteinstellungen hier angeben. Beachten Sie, dass wir unsere aus Umgebungsvariablen lesen. Wir müssen unsere Anwendung neu starten, damit diese Änderungen übernommen werden, aber wenn wir dies tun, wird unsere Anwendung dieses Mal die E-Mail erfolgreich versenden.

Die Verwendung von Links in E-Mails

Als Nächstes werden wir einige häufige Probleme zeigen, die auftreten können, wenn E-Mails versendet werden. Eins davon betrifft URLs. Angenommen, wir möchten am Ende ihrer E-Mail einen Link zum Profil des Benutzers hinzufügen. Wir könnten versuchen, dies folgendermaßen zu tun:
// app/views/user_mailer/signup_confirmation.text.erb

<%= @user.name %>,

Thank you for signing up.

<%= user_url(@user) %>

Generierung von HTML-E-Mails

Bisher haben wir einfache Text-E-Mails generiert, aber wir können auch eine HTML-Version dieser Nachricht erstellen. Dazu müssen wir eine neue Ansichtsdatei mit dem Namen signup_confirmation.html.erb nutzen und die HTML-Version der E-Mail dort hinzufügen.
// app/views/user_mailer/signup_confirmation.html.erb

<p><%= @user.name %>,</p>

<p>Thank you for signing up.</p>

<p><%=link_to "User Profile", @user %>
Eine Sache, die hier zu beachten ist, ist, dass wir Helper-Methoden genauso wie in jeder anderen Rails-Ansicht verwenden können. Jetzt wird die E-Mail, wenn sie versendet wird, die HTML-Version mit dem Link "Benutzerprofil" enthalten.

Beachten Sie, dass beim Stylen von HTML-E-Mails Vorsicht geboten ist. Wenn wir eine E-Mail senden, kommunizieren wir mit einem externen Dienst, der möglicherweise langsam reagieren oder sogar nicht verfügbar sein kann, und wir möchten diese Fehler nicht dem Benutzer anzeigen. Dies ist kein so großes Problem, wenn wir in der Produktion sendmail oder postfix verwenden, da diese ihre eigene Warteschlange haben, aber es ist dennoch ratsam, dies im Blick zu behalten.

Im Verlauf dieser Episode haben wir verschiedene Konfigurationsoptionen in unserer Entwicklungs-Konfigurationsdatei festgelegt. Es besteht die Wahrscheinlichkeit, dass wir auch Optionen zu unserer Produktions-Konfigurationsdatei hinzufügen möchten, jedoch mit unterschiedlichen Werten, die zur Anwendung passen, wenn sie sich in der Produktionsumgebung befindet.
Meld dich an und schreibe ein Kommentar