E-Mails mit Hilfe des PHPMailers versenden
Kategorie:
Veröffentlicht: 21.07.2020
Letzte Änderung: 02.10.2020
Netzwerk Offline
Dein Netzwerk ist offline, deshalb laden wir die gesamte Seite aus dem Cache. Beachte: die Inhalte könnten veraltet sein!
Für aktuelle Inhalte aktiviere bitte dein Internet!
Alter Browser
Hallo liebe Nutzer,
da wir als Coding-Plattform und Webentwickler ausschließlich auf aktuelle Technologien setzen, unterstützen wir keine veralteten Internetbrowser. Bitte schau dir doch ein paar der tollen Alternativen an, bestimmt findest du hier einen für dich passenden modernen Browser!

E-Mails einfach und sicher verschicken mit dem PHPMailer

Inhaltsverzeichnis
[[TABLE OF CONTENTS]]
access_timeGeschätzte Lesezeit ca. 8 Minuten

In diesem Artikel möchte ich dir erklären wie man heutzutage Emails in PHP verschickt. Dazu verwendet man das Composer Package PHPMailer, ein von der Community entwickeltes Framework, welches immer die neusten Standards beachtet.

Vorab die Theorie

Wenn du eine Email an mich verschicken möchtest, dann sagst du dem PHPMailer: "Hey, schick doch bitte mal eine Email an Tim". Sobald du das getan hast, versucht PHP sich über das Internet oder Lokal (je nach dem, ob du einen internen oder externen Mailserver verwendest) mit deinem SMTP-Emailserver zu verbinden und sich mit deinen Login-Daten zu authentifizieren.

Ist diese Anfrage erfolgreich beim SMTP-Server angekommen, sucht dieser sich eine Route zu meinem Emailserver. Je nach dem, wie stark meine Anforderungen an eine E-Mail zur Vermeidung von Spam sind, kann deine Anfrage nun angenommen oder abgelehnt werden. Provider wie GMX oder 1&1 haben da höhere Ansprüche, selbstgehostete Webspaces mit Plesk sind dagegen eher toleranter. Sollten deine Emails öfter abgelehnt werden, informiere einen Systemadministrator und lass dir dabei helfen, deine Domain richtig zu konfigurieren. Ob deine Email vertrauenswürdig ist oder nicht, kannst du auf Mailtester überprüfen

Wenn ich nun mit dem Thunderbird meinen Emailserver abfrage, verbinde ich mich über IMAP oder POP3 und kann je nach Protokoll (eher historisch bedingt; heute weniger relevant) entweder die Emails auf meinem Server lassen oder sie auf meinem Rechner speichern und auf meinem Mailserver löschen. Heutzutage wird im Normalfall aber nichts mehr gelöscht; beide Protokolle lassen die Emails stattdessen auf dem Server bestehen. Für Webmailnutzer ist das aber komplett irrelevant.

Installation mittels Composer

Sobald du den Composer installiert hast (wie das funktioniert erklärt dir Felix in diesem Artikel), kannst du folgenden Befehl ausführen und die neuste Version des PHPMailers wird automatisch installiert:

 composer require phpmailer/phpmailer

Wie eine Email verschickt wird?

Composer richtig importieren

Als erstes muss natürlich irgendwo in deinem Code der Composer inkludiert werden. Wichtig: Solltest du ihn versehentlich doppelt importieren, kann das zu Fehlern führen, deswegen nutze ich gerne require_once, da die Datei, falls sie bereits eingebunden wurde, nicht nochmal importiert wird und keine Fehler entstehen können.

require_once "vendor/autoload.php";

Fehler abfangen

Wenn im Produktivbetrieb dein Mailversand Probleme bereiten sollte, kannst du dem Nutzer keine Fehlermeldung ausgeben, da sich im Log auch teilweise sensible Daten von deinem Mailserver befinden könnten, deswegen empfehle ich dir deinen kompletten Mailversand in einen Try-Catch-Block zu packen oder zumindest die send() Funktion und die Ausgabe in eine Datei zu schreiben. Um diese Anleitung aber so simpel wie möglich zu halten, gebe ich diese nur aus.

require_once "vendor/autoload.php";

try {

    // neue instanz der klasse erstellen
    $mail = new PHPMailer\PHPMailer\PHPMailer(true);

} catch (PHPMailer\PHPMailer\Exception $e) {
        echo "Mailer Error: ".$mail->ErrorInfo; 
}

PHP Namespaces

Auch wenn im Beispiel vom PHPMailer die Namespaces mit use einfacher zugänglich gemacht wurden, sehe ich keinen großen Bedarf das auch bei mir zu machen, da wir die Namespaces sowieso nur je einmal brauchen. Wer das trotzdem machen möchte, kann mit use einmal alle Namespaces an den Anfang der Datei schreiben und braucht dafür dann nur den Namen nach dem letzten Slash zu schreiben. Zum Beispiel: PHPMailer\PHPMailer\PHPMailerClassPHPMailerClass

<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;

require_once "vendor/autoload.php";

// (...)

try {

    // neue instanz der klasse erstellen
    $mail = new **PHPMailer**(true); // namespace wurde bereits mit use definiert

// (...)

PHPMailer debuggen

Nun kannst du dem PHPMailer mitteilen, ob und welche Informationen er dir während des Versands ausgeben soll. Das macht im Debug-Mode Sinn oder falls du eine Version updatest und etwas nicht mehr richtig funktioniert. Im Konstruktor sagst du ihm, ob er eine Ausgabe machen darf oder nicht und definierst dann in der Klassenvariable SMTPDebug welche Informationen du haben möchtest.

Welche Fehler dir der PHPMailer noch anzeigen kann, kannst du hier nachlesen.

// neue instanz der klasse erstellen
$mail = new PHPMailer\PHPMailer\PHPMailer(true);

// gibt einen ausführlichen log aus
$mail->SMTPDebug = PHPMailer\PHPMailer\SMTP::DEBUG_SERVER; }

/*
    Profi-Lösung
*/

$debug = true; // or
$debug = false;

// neue instanz der klasse erstellen
$mail = new PHPMailer\PHPMailer\PHPMailer($debug);

if ($debug) {
        // gibt einen ausführlichen log aus
        $mail->SMTPDebug = PHPMailer\PHPMailer\SMTP::DEBUG_SERVER; }
}

Authentifizieren mittels SMTP

Nun kommen wir zur Authentifizierung. Diese erfolgt im Normalfall über SMTP. Den folgenden Code kann man also in den meisten Fällen bedenkenlos kopieren:

// authentifiziere dich über den smtp-login
$mail->isSMTP();
$mail->SMTPAuth = true;

Nun musst du dem PHPMailer deine Daten anvertrauen, damit dein Mailserver dem PHPMailer vertraut. Du benötigst einmal die Adresse deines Mailservers, das Protokoll mit dem jeweiligen Port (SMTPS oder TLS/SSL) sowie deinen Nutzernamen und dein Passwort. Ich möchte dir an dieser Stelle keine Vorschriften machen welches Protokoll du zu verwenden hast. Schau einfach schnell selbst im Internet nach dem aktuellsten Protokoll. Die meisten Mailserverbetreiber haben dafür eine eigene Dokumentation.

Thema der Tabelle "Provider Dokumentationen"
NameLink zur Dokumentation
T-Onlinehttps://www.telekom.de/hilfe/festnetz-internet-tv/e-mail/e-mail-server-e-mail-protokolle-und-e-mail-einrichtung/imap/einrichtung-imap?samChecked=true
Gmailhttps://support.google.com/mail/answer/7126229?hl=de
GMXhttps://hilfe.gmx.net/pop-imap/pop3/serverdaten.html
Stratohttps://www.strato.de/faq/mail/externes-e-mail-programm-mit-strato-e-mail-adresse-nutzen/
1&1https://hilfe-center.1und1.de/e-mail-c82645/1und1-e-mail-adresse-c84749/bedienung-c84680/e-mail-kontoeinstellungen-fuer-eine-1und1-e-mail-adresse-a783411.html
Web.dehttps://hilfe.web.de/pop-imap/pop3/serverdaten.html
// (...)
$mail->Host       = "smtp.deineDomain.de";
$mail->Port       = "587";
$mail->Username   = "deinNameHier@deineDomain.de";
$mail->Password   = "habsPasswortVergessen9934";
$mail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS;
$mail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_SMTPS;
// (...)

Zwei-Faktor-Authentifizierung

Falls du Gmail mit einer Zwei-Faktor-Authentifizierung nutzt, ist das sehr lobenswert (zumindest aus IT-Sicherheitsaspekten), aber dein Login wird scheitern. Wie du da vorgehen musst wird dir in diesem Artikel in der PHPMailer-Dokumentation nochmal genauer erklärt.

Selbst ausgestellte Zertifikate (Self-signed Certificate)

Solltest du z.B. Plesk verwenden (oder ähnliches), kann es der Fall sein, dass du dich trotz korrekter Login-Daten nicht einloggen kannst, weil das SSL-Zertifikat nicht auf deinen Emailserver ausgestellt ist. Das ist zwar ungünstig konfiguriert, du kannst es aber umgehen, indem du ihm sagst, du erlaubst selbstzertifizierte Verbindungen. Kontaktiere trotzdem deinen Webmaster und fordere ihn auf das Zertifikat auszustellen.

$mail->SMTPOptions = array(
    'ssl' => array(
          'verify_peer' => false,
          'verify_peer_name' => false,
          'allow_self_signed' => true
    ),
    'tls' => array(
        'verify_peer' => false,
        'verify_peer_name' => false,
        'allow_self_signed' => true
    )
);

Empfänger angeben

Als nächstes definieren wir einen Absendernamen und die Empfänger. Das solltest du bereits aus deinem Mailprogramm kennen. Als erstes kommt die Email-Adresse, danach kann optional noch ein Name angegeben werden, der dann statt der Adresse im Mailprogramm angezeigt wird. Das ist eine Schönheitsoptimierung und kann auch weggelassen werden.

$mail->setFrom('info@example.com', 'Information');
$mail->addAddress('info@example.com', 'Information');
$mail->addAddress('info@example.com');
$mail->addReplyTo('info@example.com', 'Information');
$mail->addCC('info@example.com');
$mail->addBCC('info@example.com', 'Information');

Dateien anhängen an eine Email

Möchtest du in deiner Email Bilder, Dokumente, Musik, Videos oder anderweitige Dateien versenden, hilft dir die addAttachment() Funktion. Diese liest den Inhalt der Datei aus, inkludiert diesen und benennt über den optionalen Parameter die Datei auch um (sehr empfehlenswert).

$mail->addAttachment("/home/webuser/Schreibtisch/Spiderman.png");
$mail->addAttachment("/home/webuser/Schreibtisch/Spiderman.png", "Spiderman.png");

HTML-Inhalt und Fallback

Bevor wir nun unsere Email versenden, müssen wir uns aber noch um das wichtigste kümmern: Wir brauchen Inhalt! Dieser besteht normalerweise immer aus einer HTML-Version und einer, falls der Nutzer HTML-Mail deaktiviert hat oder Uraltsoftware verwendet, Textversion, die nochmal grob den Inhalt zusammenfasst.

WARNUNG!! Wenn du einen Webmailer oder ein anderes cooles neues Mailprogramm wie den Thunderbird benutzt, betrifft dich das jetzt weniger, aber die Kollegen der Microsoftfraktion haben mit Outlook noch ältere Internet Explorer Technologie und ihnen wird es die Seite zerschießen, wenn du responsives HTML5 (aktueller Standard) verwendest. Bist du auf MS-Kunden angewiesen (hauptsächlich Geschäftskunden), dann würde ich dein neues Emailtemplate mit MJML designen, eine spezielle, ähnlich wie HTML, auf XML basierende Containersprache, mit der dann HTML generiert wird. HTML sollte überall gut funktionieren.

$mail->isHTML(true);
$mail->Subject = '';
$mail->Body    = '';
$mail->AltBody = '';

Und Tschüss!

Wenn du nun alles andere so konfiguriert hast, dass es funktioniert, kannst du deine Email endlich wegschicken. Du hast es geschafft! Ich erinnere dich nochmals an den Try-Catch-Block!

// (...)
try {
    // (...)
    $mail->send();
} catch (PHPMailer\PHPMailer\Exception $e) {
    echo "Message could not be sent. Mailer Error: ".$mail->ErrorInfo; 
}

Beispielcode

Zum Abschluss möchte ich dir nochmal einen fertigen Code zeigen. Du darfst ihn gerne kopieren und bei dir einfügen.

$debug = true; // or
$debug = false;

require_once "vendor/autoload.php";

try {
        // neue instanz der klasse erstellen
        $mail = new PHPMailer\PHPMailer\PHPMailer($debug);

        if ($debug) {
                // gibt einen ausführlichen log aus
                $mail->SMTPDebug = PHPMailer\PHPMailer\SMTP::DEBUG_SERVER; }
        }

        // authentifiziere dich über den smtp-login
        $mail->isSMTP();
        $mail->SMTPAuth = true;

        // login
        $mail->Host       = "smtp.deineDomain.de";
        $mail->Port       = "587";
        $mail->Username   = "deinNameHier@deineDomain.de";
        $mail->Password   = "habsPasswortVergessen9934";
        $mail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS;
        $mail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_SMTPS;
        $mail->SMTPOptions = array(
            'ssl' => array(
                  'verify_peer' => false,
                  'verify_peer_name' => false,
                  'allow_self_signed' => true
            ),
            'tls' => array(
                'verify_peer' => false,
                'verify_peer_name' => false,
                'allow_self_signed' => true
            )
        );

        $mail->addAttachment("/home/webuser/Schreibtisch/Spiderman.png", "Spiderman.png");

        $mail->isHTML(true);
        $mail->Subject = utf8_encode($Subject);
        $mail->Body    = utf8_encode($Html);
        $mail->AltBody = utf8_encode($Text);

        $mail->send();

} catch (PHPMailer\PHPMailer\Exception $e) {
    echo "Message could not be sent. Mailer Error: ".$mail->ErrorInfo; 
}

oder als simple Funktion:

<?php

$debug = true; // or
$debug = false; 

require_once "vendor/autoload.php";

if(sendEMail('mail@example.de', 'Your Name', 'Here is your Spiderman!', '<h1>Spiderman!</h1>', 'Spiderman!', array("Spiderman.png" => "/path/to/img.png"))) 
{ echo "\nPasst! Schau mal in dein Postfach Spiderman ist da!\n"; }
else
{ echo "\nERROR! Ein interner Fehler ist aufgetreten! Die E-Mail konnte nicht korrekt zugestellt werden\n"; }

function sendEMail($receiver,$receiverName,$subject,$html,$text,$AttmFiles=array()){
    global $debug;

    $mail = new PHPMailer\PHPMailer\PHPMailer($debug);

    if ($debug)
    { $mail->SMTPDebug = PHPMailer\PHPMailer\SMTP::DEBUG_SERVER; }

    $mail->isSMTP();
    $mail->SMTPAuth   = true;
    $mail->Host       = "example.de";
    $mail->Port       = "465";
    $mail->Username   = "mail@example.de";
    $mail->Password   = "deinpasswort";
    // $mail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS; // port 587
    $mail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_SMTPS; // port 465
    $mail->CharSet    = 'utf-8';
    $mail->Debugoutput = 'html';
    $mail->SMTPOptions = array(
      'ssl' => array(
          'verify_peer' => false
          ,'verify_peer_name' => false
          ,'allow_self_signed' => true
      ),
      'tls' => array(
        'verify_peer' => false
        ,'verify_peer_name' => false
        ,'allow_self_signed' => true
      )
    );

    $mail->setFrom("mail@example.de", 'Dein Name');
    $mail->addAddress($receiver, $receiverName);

    foreach($AttmFiles as $key => $value)
    { $mail->addAttachment($value, $key); }

    $mail->isHTML(true);
    $mail->Subject = $subject;
    $mail->Body    = $html;
    $mail->AltBody = $text;

    try {
        $mail->send();
        return true;
    } catch (PHPMailer\PHPMailer\Exception $e) {
        if($debug)
        { echo "Message could not be sent. Mailer Error: ".$mail->ErrorInfo; }
        return false;
    }
}

Kommentare zum Artikel

Es sind noch keine Kommentare vorhanden? Sei der/die Erste und verfasse einen Kommentar zum Artikel "E-Mails mit Hilfe des PHPMailers versenden"!

Kommentar Schreiben:

keyboard_arrow_up
Home Menü Suche
X