Quantcast
Channel: PHP Gangsta - Der PHP Blog mit Praxisbezug » Zend_Mail
Viewing all articles
Browse latest Browse all 3

Ein paar Zend_Mail Tricks

$
0
0

Wer Mails verschickt, nutzt bei sehr einfachen (Admin) E-Mails meistens die eingebaute mail() Funktion. Sobald es aber darum geht komplexere E-Mails zu versenden wird man wahrscheinlich eine Klasse benutzten, die es einem einfacher macht, Anhänge anzuhängen, einen text/plain und einen text/html Teil mitzusenden, zusätzliche Empfänger zu definieren oder inline-Bilder gleich mit in die Email zu packen.

Es gibt dutzende gute Mail-Klassen und Libraries da draußen (ezcMail, htmlMimeMail5), ich benutze häufig Zend_Mail. Mit den verschiedenen Zend_Mail_Transport_* Klassen ist es möglich, die Mails über sendmail (sprich über mail()) zu versenden, oder aber beispielsweise mit Hilfe des SMTP-Protokolls an einen SMTP-Server zu übergeben. Seit wenigen Monaten neu ist Zend_Mail_Transport_File, womit die E-Mail nicht versendet wird, sondern “nur” in eine Datei geschrieben wird. Ich habe mir früher einen solchen Adapter selbst geschrieben, nun ist er im Zend Framework enthalten.

Mit diesem Adapter ist es sehr einfach möglich, beispielsweise in der Entwicklungsumgebung keine E-Mails zu versenden, damit nicht aus Versehen beim Testen des Abschickens eines Formulars wirkliche E-Mails versendet werden, sondern nur zu Debuggingzwecken in eine Datei geschrieben wird. Beispielsweise so:

[production]
;    Config we use for production:
resources.mail.transport.type = smtp
resources.mail.transport.host = "smtp.example.com"
resources.mail.transport.auth = login
resources.mail.transport.username = myUsername
resources.mail.transport.password = myPassword

[development]
;    This options for the dev env:
resources.mail.transport.type = file
resources.mail.transport.path = "/tmp/send" 

Mit dem Adapter ist es auch möglich, den Mail-Versand zu testen mittels Unit-Tests, der Inhalt der Datei kann dann einfach gegen die erwartete Ausgabe geprüft werden.

In meinem eigenen Repertoire habe ich noch einen Adapter, mit dem man dieses Schreiben in eine Datei umgehen kann und den generierten E-Mail Quelltext direkt abfragen kann. Auch dieser Adapter kann natürlich gut zu Testzwecken genutzt werden, und man benötigt keinen Speicherplatz/Schreibrechte:

<?
class App_Mail_Transport_Null extends Zend_Mail_Transport_Smtp {
    /**
     * DON'T send an email via the SMTP connection protocol
     *
     * @return void
     */
    public function _sendMail()
    {
    }

    public function getSmtpMailSource()
    {
        if (empty($this->header)) {
            throw new Exception('Mail source could not be returned, you have to call send() first!');
        }

        return $this->header . Zend_Mime::LINEEND . $this->body;
    }
}

$transport = new App_Mail_Transport_Null();
$mail->send($transport);
$messageString = $transport->getSmtpMailSource();

Das Senden von vielen E-Mails wird kompliziert wenn man möglichst schnell möglichst viele E-Mails versenden möchte. Eine der schnellsten Methoden ist es, die generierte E-Mail in eine Datei zu schreiben und dann in das Pick-Up Verzeichnis des Postfix zu schieben. Dazu kann der oben gezeigte File-Adapter genutzt werden. Falls dieser Weg zu umständlich ist (oder kein Zugriff auf dieses Verzeichnis möglich ist), bleibt nur der Versand über SMTP. Aber auch da gibt es einige feine Unterschiede. Normalerweise wird für jede E-Mail eine eigene TCP/IP Verbindung geöffnet und dann für jede E-Mail ein SMTP-Dialog abgespult. Doch es geht auch effizienter, indem man eine Verbindung wiederbenutzt. Hier erstmal das normale Vorgehen:

$tr = new Zend_Mail_Transport_Smtp("mail.example.com")
Zend_Mail::setDefaultTransport($tr);

for ($i = 0; $i < 5; $i++) {
    $mail = new Zend_Mail();
    $mail->setBodyText("This is the text of the mail. $i");
    $mail->setFrom("sender@example.com", "Some Sender $i")
    $mail->addTo("recipient@example.com", "Some Recipient $i");
    $mail->setSubject("Test Subject $i");
    $mail->send();
}

Besser ist es jedoch so:

$tr = new Zend_Mail_Transport_Smtp("mail.example.com");
Zend_Mail::setDefaultTransport($tr);

$mail = new Zend_Mail();
for ($i = 0; $i < 5; $i++) {
    $mail->setBodyText("This is the text of the mail $i.");
    $mail->setFrom("sender@example.com", "Some Sender $i");
    $mail->addTo("recipient@example.com", "Some Recipient $i");
    $mail->setSubject("Test Subject $i");
    $mail->send();
}

Im zweiten Fall bleibt die Verbindung bestehen, und es wird im SMTP-Dialog einfach ein RSET gesendet und dann die nächste E-Mail verschickt.

Bei dieser Methode gilt jedoch zu beachten dass viele SMTP-Server die Anzahl der E-Mails, die innerhalb eines SMTP-Dialogs versendet werden dürfen, beschränken.


Viewing all articles
Browse latest Browse all 3

Latest Images





Latest Images