Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Geleitwort des Fachgutachters
Einleitung
1 Einführung
2 Installation
3 Erste Schritte
4 Einführung in Ruby
5 Eine einfache Bookmarkverwaltung
6 Test-Driven Development
7 Rails-Projekte erstellen
8 Templatesystem mit ActionView
9 Steuerzentrale mit ActionController
10 Datenbankzugriff mit ActiveRecord
11 E-Mails verwalten mit ActionMailer
12 Nützliche Helfer mit ActiveSupport
13 Ajax on Rails
14 RESTful Rails und Webservices
15 Rails mit Plug-ins erweitern
16 Performancesteigerung
17 Sicherheit
18 Veröffentlichen einer Rails-Applikation auf einem Server
Ihre Meinung?

Spacer
 <<   zurück
Ruby on Rails 2 von Hussein Morsy, Tanja Otto
Das Entwickler-Handbuch
Buch: Ruby on Rails 2

Ruby on Rails 2
geb., mit DVD
699 S., 39,90 Euro
Rheinwerk Computing
ISBN 978-3-89842-779-1
Online bestellenPrint-Version jetzt bestellen
* versandkostenfrei in (D) und (A)
Pfeil 11 E-Mails verwalten mit ActionMailer
  Pfeil 11.1 Beispielprojekt: Kontaktformular
  Pfeil 11.2 HTML-E-Mails
  Pfeil 11.3 E-Mails mit Anhängen
  Pfeil 11.4 Konfiguration

11 E-Mails verwalten mit ActionMailer

Jede Web-Applikation muss E-Mails versenden können. Sei es eine E-Mail aus einem Kontaktformular heraus oder die Bestätigungs-E-Mail zu einem Buchungsvorgang.

Features

ActionMailer ist ein Bestandteil des Rails-Framework und bietet einige Features:

  • Versenden von E-Mails
    als Text- oder als HTML-E-Mail. Beides gleichzeitig geht auch, dann kann der Mail-Client entscheiden, welches Format er anzeigt.
  • Versenden von Dateianhängen
    ist mit ActionMailer sogar relativ einfach zu realisieren.

Rheinwerk Computing - Zum Seitenanfang

11.1 Beispielprojekt: Kontaktformular  topZur vorigen Überschrift

Beispiel

Die Funktionsweise von ActionMailer zum Versenden von E-Mails wollen wir anhand eines Kontaktformulars zeigen. Der Kunde soll seine Daten und seine Nachricht in das Formular eingeben können, beim Absenden des Formulars soll die Nachricht an den Webseitenbetreiber geschickt werden und der Kunde soll eine Bestätigungs-E-Mail erhalten. Es sollen also zwei E-Mails mit unterschiedlichen Inhalten versendet werden.

Unsere Applikation soll contact heißen. Obwohl wir für ein Kontaktformular eigentlich keine Datenbank benötigen, sondern nur die E-Mail-Funktion, nutzen wir trotzdem eine Datenbank, weil es in Rails viel einfacher ist, wenn ein datenbankbasiertes Model dahinter steht.

Als Datenbanksystem werden wir in diesem Fall SQLite3 verwenden, da es den Vorteil bietet, das wir keine Datenbank anlegen müssen, weil SQLite3 dateibasiert ist und die Dateien automatisch angelegt werden.

Sie können natürlich auch MySQL verwenden, müssen dann aber die entsprechende Datenbank anlegen.

Mehr zum Thema Datenbanken erfahren Sie in Kapitel 10.

Projekt generieren

Wir generieren unser Beispielprojekt mit dem Befehl:

rails contact
cd contact

Wir benötigen einen Controller, Views und ein Model, um unser Kontaktformular nutzen zu können. Da man eine Nachricht über ein Kontaktformular auch als eine Ressource betrachten kann (man kann neue Nachrichten hinzufügen, anzeigen, bearbeiten, und löschen), werden wir den scaffold -Generator zum Erzeugen einer Resource nutzen, der einiges an Code automatisch generiert und uns damit die Arbeit erleichtert.

Benötigte Felder

Unser Model soll contact_message heißen, und der Einfachheit halber wollen wir nur die Felder name, email für die E-Mail-Adresse und message für die Nachricht nutzen. Die Felder name und email sind vom Typ string und das Feld message ist vom Typ text, da es möglich sein soll mehr als 256 Zeichen in

Scaffold

einer Nachricht zu speichern. Wir wechseln also in das Projektverzeichnis contact und führen folgenden Befehl aus:

ruby script/generate scaffold contact_message name:string \
			      email:string message:text

Der Generator hat automatisch die Model-Datei, die Controller-Datei, die Views und die Migration-Datei erstellt.

Migration

Sollten wir doch noch weitere Felder benötigen, könnten wir jetzt die Migration-Datei öffnen und weitere Felder hinzufügen, ansonsten führen wir die Migration mit dem Befehl rake db:migrate aus.

Test im Browser

Wir können unsere Applikation im Browser testen. Dazu starten wir in der Konsole den lokalen Rails-Server mit dem Befehl

ruby script/server

und rufen über http://localhost:3000/contact_messages unsere Applikation im Browser auf:

Abbildung  E-Mail-Applikation

Neue Nachricht anlegen

Über den Link »New contact message« gelangen wir zum Formular:

Abbildung  Neue Nachricht verfassen

Nachricht anzeigen

Wenn wir das Formular absenden, wird uns die neue Nachricht angezeigt:

Abbildung  So sieht die Nachricht aus

Alle Nachrichten

Über den Zurück-Link gelangen wir zur Übersicht aller Nachrichten:

Abbildung  Liste aller Nachrichten

Was wir erst einmal nicht benötigen, ist, dass eine Liste aller angelegten Nachrichten ausgegeben wird, und wir benötigen auch keine Funktion zum Editieren und Löschen von Nachrichten. Das könnte man alles nutzen, wenn man die Nachrichten verwalten möchte, aber für uns sind das erst einmal überflüssige Funktionen bzw. Actions im Controller.

Benötigte Actions

Wir benötigen nur die Actions

  • new
    stellt das Formular zum Anlegen einer Nachricht zur Verfügung.
  • create
    speichert die neue Nachricht in der Datenbank. Hier werden wir auch das Versenden der E-Mails hinzufügen.
  • show
    zeigt dem Kunden die Zusammenfassung seiner gesendeten Nachricht an.

Nicht benötigte Actions

Die anderen Actions können wir aus dem Controller löschen. Dazu öffnen wir das Projekt in einem Editor und löschen die Actions index, edit, update und destroy aus der Datei contact_messages_controller.rb im Verzeichnis app/controllers . Wir können auch die entsprechenden View-Dateien index.html.erb und edit.html.erb aus dem Verzeichnis app/views/contact_messages löschen. In den verbleibenden beiden View-Dateien new.html.erb und show.html.erb können wir die Links entfernen.

mailer

Nun können wir eine neue Kontaktnachricht über das Formular anlegen, aber es wird noch keine E-Mail verschickt. Um E-Mails versenden zu können, setzen wir den mailer -Generator ein, der uns neben Testdateien ein Model generiert, das für das Versenden der E-Mails zuständig ist, und Template-Dateien, in denen wir die Texte für die E-Mails hinterlegen können.

Das von dem Generator mailer erzeugte Model wird kein datenbankbasiertes Model sein, das von ActiveRecord erbt, so wie das Model ContactMessage für das Kontaktformular. Das für den Mailversand zuständige Model wird von ActionMailer erben.

Generator einsetzen

Der mailer -Generator erwartet einen Namen und eine Liste von Views für die einzelnen E-Mails die versendet werden sollen, als Parameter:

ruby script/generate mailer MailerName view1 view2

Unser mailer soll contact_mailer heißen und die Views für die beiden zu versendenden E-Mails confirmation und message:

ruby script/generate mailer contact_mailer confirmation message

Es werden folgende Dateien erzeugt:

exists  app/models/
create  app/views/contact_mailer
exists  test/unit/
create  test/fixtures/contact_mailer
create  app/models/contact_mailer.rb
create  test/unit/contact_mailer_test.rb
create  app/views/contact_mailer/confirmation.erb
create  test/fixtures/contact_mailer/confirmation
create  app/views/contact_mailer/message.erb
create  test/fixtures/contact_mailer/message

Erzeugte Dateien

Neben diversen Testdateien werden die Model-Datei contact_mailer.rb im Verzeichnis app/models und die beiden Templates confirmation.erb und message.erb im Verzeichnis app/views/contact_mailer erzeugt. Das Template confirmation.erb werden wir nutzen, um eine Bestätigungs-E-mail an den Kunden zu senden, und das Template message.erb, um eine Zusammenfassung der Daten an den Webseitenbetreiber zu schicken.

Bestätigungs- E-Mail

Zunächst möchten wir die Bestätigungs-E-mail für den Kunden anpassen. Wir wählen einen ganz einfachen Standardtext und geben diesen in die confirmation.erb ein:

Listing  app/views/contact_mailer/confirmation.erb

Vielen Dank für Ihre Nachricht.

Wir werden uns so schnell wie möglich bei Ihnen melden.

Das Model ContactMailer erbt, wie bereits erwähnt, im Gegensatz zum Model ContactMessage von ActionMailer::Base und enthält die beiden Methoden confirmation und message:

Listing  app/models/contact_mailer.rb

class ContactMailer < ActionMailer::Base

  def confirmation(sent_at = Time.now)
    @subject    = 'ContactMailer#confirmation'
    @body       = {}
    @recipients = ''
    @from       = ''
    @sent_on    = sent_at
    @headers    = {}
  end

  def message(sent_at = Time.now)
    @subject    = 'ContactMailer#message'
    @body       = {}
    @recipients = ''
    @from       = ''
    @sent_on    = sent_at
    @headers    = {}
  end
end

Ein Mailer-Model enthält immer so viele Methoden, wie es E-Mail-Templates gibt, die auch so heißen, wie die Templates.

Konfiguration

Den beiden Methoden können Sie über den optionalen Parameter sent_at den Zeitpunkt übergeben, an dem die E-Mail versendet werden soll. Da dieser Parameter optional ist, können Sie ihn auch weglassen. Standardmäßig wird der Wert von sent_at auf Time.now gesetzt, was bedeutet, dass die E-Mail zum Zeitpunkt des Aufrufs der Methode versendet wird.

Darüber hinaus können Sie in den Methoden innerhalb des Mailer-Models folgende Variablen setzen:

  • @subject
    Betreff der E-Mail
  • @body
    Hier können Sie den Text eingeben, wenn Sie eine Textmail versenden und den Text nicht in das ActionView-Template eingeben. Oder Sie können über @body Variablen in Form eines Hashs an das Action View-Template übergeben.
  • @recipients
    Eine oder mehrere Empfänger-Adressen der E-Mail. Bei nur einem Empfänger wird die eine E-Mail-Adresse als String übergeben, bei mehreren Empfängern wird ein Array mit den einzelnen E-Mail-Adressen übergeben.
  • @from
    Absender-Adresse der E-Mail
  • @sent_on
    Zeitpunkt zu dem die E-Mail versendet werden soll. Wird auf den Wert des optionalen Parameters sent_at gesetzt.
  • @headers
    Optionale Variable. Hier können Header-Informationen der E-Mail als Hash übergeben werden.

In unserem Beispiel haben wir die Werte in der Methode confirmation wie folgt gesetzt:

def confirmation(sent_at = Time.now)
  @subject    = 'Ihre Kontaktnachricht erhalten'
  @body       = {}
  @recipients = 'tanja@test.lu'
  @from       = 'info@railsbuch.de'
  @sent_on    = sent_at
  @headers    = {}
end

Standardtext

Da wir einen Standardtext für die Bestätigungs-E-mail an die Kunden im Template confirmation.erb definiert haben und auch immer nur diesen Standardtext versenden möchten, benötigen wir keine Variablen innerhalb unseres Templates. Deshalb lassen wir die Variable @body leer. Der Einfachheit halber haben wir im ersten Schritt die E-Mail-Adresse für den Empfänger der E-Mail statisch eingesetzt. Im nächsten Schritt werden wir zeigen, wie Sie die E-Mail-Adresse aus dem Formularfeld an die Methode übergeben können. Wir wollen keine besonderen Header-Informationen übergeben, deshalb lassen wir die Variable @headers auch leer.

Zeitpunkt zum Versenden der E-Mail

Wir möchten unsere Bestätigungs-E-mail dann versenden, wenn ein Kunde das Kontaktformular ausgefüllt und abgeschickt hat und die Nachricht in der Datenbank gespeichert werden konnte. Das entspricht im ContactMessagesController in der Action create der Stelle, an der abgefragt wird, ob das Speichern erfolgreich war. Innerhalb dieser Abfrage müssen wir das Model ContactMailer aufrufen, um die Bestätigungs-E-mail zu versenden. Allerdings rufen wir dazu nicht einfach die Methode confirmation aus dem Model auf, sondern per Konvention wird dem Methodennamen ein deliver_ vorangestellt, so dass wir die Methode deliver_confirmation aufrufen müssen:

Listing  app/controllers/contact_messages_controller.rb

def create
  @contact_message = ContactMessage.new(
		     params[:contact_message])
  respond_to do |format|
    if @contact_message.save
      ContactMailer.deliver_confirmation
      flash[:notice] = 'ContactMessage was successfully
			created.'
      format.html { redirect_to contact_message_url(
		    @contact_message) }
      format.xml  { head :created, :location =>
		    contact_message_url(@contact_message) }
    else
      format.html { render :action => "new" }
      format.xml  { render :xml =>
		    @contact_message.errors.to_xml }
    end
  end
end

Da wir keine XML-Anfrage bearbeiten möchten, können wir die Methode create wie folgt vereinfachen:

Listing  app/controllers/contact_messages_controller.rb

def create
  @contact_message = ContactMessage.new(
		     params[:contact_message])
  if @contact_message.save
      ContactMailer.deliver_confirmation
      flash[:notice] = 'Vielen Dank für Ihre Nachricht.'
      redirect_to(@contact_message)
  else
     render :action => "new"
  end
end

Wenn wir jetzt den lokalen Rails-Server erneut starten und unser Kontaktformular ( http://localhost:3000/contact_messages/new ) ausfüllen und absenden, können wir nicht sehen, ob die E-Mail versendet wurde, da in der Entwicklungsumgebung normalerweise keine E-Mails versendet werden.

Kontrolle mit Hilfe der Konsole

Aber in dem Konsole-Fenster, in dem wir den lokalen Rails-Server mit ruby script/server gestartet haben, wird alles protokolliert. Zum einen finden wir hier den INSERT -Befehl, der die Nachricht in der Datenbank gespeichert hat, und wir finden hier einen Eintrag Sent mail, innerhalb dem protokolliert wurde, an wen welche E-Mail mit welchem Betreff und Text versendet wurde:

INSERT INTO contact_messages ("message", "name", "updated_at",
"created_at", "email") VALUES('Das ist ein Test', 'Tanja',
'2008-01-08 21:33:20', '2008-01-08 21:33:20', 'tanja@test.lu')

Sent mail:
Date: Tue, 8 Jan 2008 21:33:20 +0100
From: info@railsbuch.de
To: tanja@test.lu
Subject: Ihre Kontaktnachricht erhalten
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8

Vielen Dank für Ihre Nachricht.

Wir werden uns so schnell wie möglich bei Ihnen melden.

Sollten die Umlaute innerhalb des Konsole-Fensters nicht richtig dargestellt werden, muss Sie das nicht beunruhigen. Das passiert nur in der Konsole. Innerhalb der E-Mail die versendet wird, werden alle Zeichen korrekt dargestellt.

Da wir in der Variablen @recipients innerhalb der Methode confirmation eine statische E-Mail-Adresse angegeben haben, wird unsere Bestätigungs-E-mail immer an die gleiche Adresse gesendet. Sie soll aber an die E-Mail-Adresse, die im Kontaktformular eingegeben wurde gesendet werden.

Parameter übergeben

Wir können die E-Mail-Adresse aus dem Formular über einen Parameter in die Methode confirmation übergeben. Im ContactMessagesController steht uns das Objekt @contact_message zur Verfügung. Dieses Objekt verfügt über das Feld »email« (welche Felder zur Verfügung stehen, können Sie in der Datei db/schema.rb nachschauen), auf das wir zugreifen können.

Wir müssen nur den Parameter, über den wir die E-Mail-Adresse übergeben, in der Methode confirmation hinzufügen und ihn innerhalb der Methode an die Variable @recipients übergeben.

Listing  app/controllers/contact_messages_controller.rb

def create
  @contact_message = ContactMessage.new(
		     params[:contact_message])
  if @contact_message.save
    ContactMailer.deliver_confirmation(@contact_message.email)
    flash[:notice] = 'Vielen Dank für Ihre Nachricht.'
    redirect_to(@contact_message)
  else
    render :action => "new"
  end
end

Parameter empfangen

Die übergebene E-Mail-Adresse empfangen wir in der Methode confirmation im Model ContactMailer über den Parameter email, der innerhalb der Methode an die Variable @recipients übergeben wird:

Listing  app/models/contact_mailer.rb

def confirmation(email, sent_at = Time.now)
  @subject    = 'Ihre Kontaktnachricht erhalten'
  @body       = {}
  @recipients = email
  @from       = 'info@railsbuch.de'
  @sent_on    = sent_at
  @headers    = {}
end

Wenn Sie jetzt einen erneuten Test durchführen, sehen Sie in der Ausgabe im Konsole-Fenster, dass die E-Mail-Adresse aus dem Formular übernommen wurde:

Abbildung  Test des Formulars

INSERT INTO contact_messages ("message", "name", "updated_at",
"created_at", "email") VALUES('Meine erste Nachricht',
'Tanja', '2008-01-08 21:44:33', '2008-01-08 21:44:33',
'tanja@railsbuch.de')
Sent mail:
Date: Tue, 8 Jan 2008 21:44:33 +0100
From: info@railsbuch.de
To: tanja@railsbuch.de
Subject: Ihre Kontaktnachricht erhalten
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8

Vielen Dank für Ihre Nachricht.

Wir werden uns so schnell wie möglich bei Ihnen melden.

Es soll auch eine E-Mail mit der Zusammenfassung aller Daten aus dem Kontaktformular an den Webseitenbetreiber gesendet werden. Für das Versenden dieser E-Mail haben wir im Model ContactMailer die Methode message und das entsprechende Template message.erb angelegt.

@body

Da wir in dieser E-Mail alle Daten ausgeben möchten, Name, E-Mail und die Nachricht selbst, ist es erforderlich, dass wir diese Werte aus dem Formular in der E-Mail andrucken. Das heißt, wir müssen die Werte aus dem ContactMessagesController an das Template, in dem der Text für die E-Mail generiert wird, übergeben. Innerhalb der Methode message steht uns dazu die Varibale @body zur Verfügung. Das heißt, die Werte müssen aus dem Controller in die Methode übergeben werden und innerhalb der Methode an die Variable @body.

Objekt übergeben

Da wir im Gegensatz zu der Bestätigungs-E-mail an den Kunden, diesmal alle Werte an die Methode deliver_message übergeben müssen, übergeben wir nicht mehr einzelne Werte, sondern das ganze Objekt @contact_message aus dem ContactMessagesController:

Listing  app/controllers/contact_messages_controller.rb

def create
  @contact_message = ContactMessage.new(
		     params[:contact_message])
  if @contact_message.save
    ContactMailer.deliver_confirmation(@contact_message.email)
    ContactMailer.deliver_message(@contact_message)
    flash[:notice] = 'Vielen Dank für Ihre Nachricht.'
    redirect_to(@contact_message)
  else
    render :action => "new"
  end
end

Die Methode message empfängt das übergebene Objekt in dem Parameter contact_message und übergibt diesen Parameter in einem Hash an die Variable @body:

Listing  app/models/contact_mailer.rb

def message(contact_message, sent_at = Time.now)
  @subject    = 'Neue Kontaktanfrage'
  @body       = {:contact_message => contact_message}
  @recipients = 'info@railsbuch.de'
  @from       = contact_message.email
  @sent_on    = sent_at
  @headers    = {}
end

E-Mail-Text

Nachdem auch die anderen Variablen in der Methode message gesetzt sind, können wir den E-Mail-Text im Template message.erb gestalten. Da wir das Objekt contact_message in der Variablen @body übergeben haben, steht es uns im Template als Instanzvariable @contact_message zur Verfügung:

Listing  app/views/contact_mailer/message.erb

Name: <%= @contact_message.name %>

E-Mail: <%= @contact_message.email %>

Nachricht: <%= @contact_message.message %>

Wenn wir jetzt einen erneuten Test durchführen, sehen wir im Konsole-Fenster zwei Sent mail -Einträge. Einen für unsere Bestätigungs-E-mail an den Kunden und einen für die Zusammenfassung an den Webseitenbetreiber:

INSERT INTO contact_messages ("message", "name", "updated_at",
"created_at", "email") VALUES('Meine erste Nachricht',
'Tanja', '2008-01-08 21:54:06', '2008-01-08 21:54:06',
'tanja@railsbuch.de')
Sent mail:
Date: Tue, 8 Jan 2008 21:54:06 +0100
From: info@railsbuch.de
To: tanja@railsbuch.de
Subject: Ihre Kontaktnachricht erhalten
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8

Vielen Dank für Ihre Nachricht.

Wir werden uns so schnell wie möglich bei Ihnen melden.

Sent mail:
Date: Tue, 8 Jan 2008 21:54:06 +0100
From: tanja@railsbuch.de
To: info@railsbuch.de
Subject: Neue Kontaktanfrage
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8

Name: Tanja

E-Mail: tanja@railsbuch.de

Nachricht: Meine erste Nachricht

In Rails kann man also relativ einfach E-Mails verschicken. Durch Einsatz des mailer -Generators, dem der Name des Models und die einzelnen Views übergeben werden müssen, wird uns sehr viel Arbeit abgenommen. Der Generator erzeugt neben Testdateien das Mailer-Model mit den erforderlichen Methoden und die View-Dateien, die wir nur noch konfigurieren und an unsere Bedürfnisse anpassen müssen. Das Versenden erfolgt dann einfach durch Aufruf des Mailer-Models mit der Methode deliver_Methodenname, der wir eventuell in dem entsprechenden Controller individuelle Parameter übergeben können.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
 <<   zurück
  Zum Katalog
Zum Katalog: Ruby on Rails 2
Ruby on Rails 2
Jetzt bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Ruby on Rails 3.1






 Ruby on Rails 3.1


Zum Katalog: Responsive Webdesign






 Responsive Webdesign


Zum Katalog: Suchmaschinen-Optimierung






 Suchmaschinen-
 Optimierung


Zum Katalog: JavaScript






 JavaScript


Zum Katalog: Schrödinger lernt HTML5, CSS3 und JavaScript






 Schrödinger lernt
 HTML5, CSS3
 und JavaScript


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de