PHPBoek();
9 E-mail via PHP
Een van de meest gebruikte mogelijkheden van PHP is de functie om een e-mail te kunnen verzenden. De e-mailfunctie maakt het mogelijk om PHP te gebruiken voor de afhandeling van een mailformulier. Ook in meer ingewikkelder systemen komt de e-mailfunctie regelmatig terug. Denk hierbij aan e-mails die verzonden worden voor accountbevestiging of opties om een verloren wachtwoord terug op te vragen. In feite komt de e-mailfunctie terug in ieder PHP script dat iets doet met gebruikersregistratie.
Theorie
De functie waar het in dit hoofdstuk allemaal om draait is mail()
:
$to
, string $subject
, string $message
[, mixed $additional_headers
[, string $additional_parameters
]] )
Achtereenvolgens moeten als parameters voor $to
het e-mailadres van de ontvanger worden ingevoerd, voor $subject
het onderwerp dat aan de e-mail wordt gegeven en $message
bevat de daadwerkelijke inhoud van het e-mailbericht.
In $additional_headers
kunnen een of meerdere headers worden opgenomen die aan het verzonden bericht worden toegevoegd. Eén header is verplicht en dat is de From-header die aangeeft wie de afzender van het bericht is. In het algemeen is het niet noodzakelijk om andere headers dan de From-header aan een bericht toe te voegen.
Daar waar $to
één enkel e-mailadres is, mag het e-mailadres in de From-header in de uitgebreide vorm worden geschreven:
Naam <naam@provider.net>
Het voordeel van deze uitgebreide vorm is dat de ontvanger direct de naam van de afzender in beeld krijgt en niet alleen het e-mailadres.
Voorbeeld
Bovenstaande theorie kan er in PHP code als volgt uit zien:
$from = 'From: Voornaam Achternaam <verzender@domain.tld>';
$subject = 'onderwerp van dit bericht';
$message = 'Beste ontvanger,
Dit is mijn eerste mailtje dat ik via PHP verstuur!';
mail($to, $subject, $message, $from);
Merk op dat er voor naam en adres van de verzender expliciet From: is vermeld. Zonder deze vermelding weet PHP niet wat voor een soort header het betreft en kan het bericht niet worden verzonden.
Het bericht is in dit voorbeeld een plain text bericht. Geen HTML, geen opmaak, alleen tekst. Het is mogelijk om zonder <br> of \n meerdere regels in het bericht te gebruiken, simpelweg door het bericht over meerdere regels in de PHP code te zetten. De meeste moderne e-mailclients geven dit soort berichten correct over meerdere regels weer.
Verzendcontrole
Indien het bericht succesvol aan de mailserver is aangeboden zal de functie mail()
de waarde TRUE
retourneren. Als het bericht niet succesvol verzonden kon worden, zal de waarde FALSE
geretourneerd worden. Dit gegeven kan gebruikt worden om te rapporteren of een bericht verzonden is of niet:
echo 'Bericht is verzonden.';
}
else {
echo 'Bericht niet verzonden.';
}
Merk op dat dit niets zegt over of een e-mail daadwerkelijk is aangekomen of niet.
HTML E-mail
Naast plain text e-mail is het ook mogelijk om berichten in HTML-opmaak te verzenden. Het principe is grotendeels hetzelfde. Uiteraard wordt het bericht nu in HTML opgemaakt en in dat geval zal dus wel van <br> gebruik moeten worden gemaakt om een nieuwe regel in te voegen.
Behalve het bericht in HTML worden er nog twee headers toegevoegd die aan de mailclient van de ontvanger duidelijk moeten maken dat het hier om een HTML e-mailbericht gaat. Samen met de From:-header worden er dus drie headers aan het bericht toegevoegd. Headers worden met een CRLF (ofwel \r\n) van elkaar gescheiden.
Onderstaand voorbeeld laat zien hoe met HTML e-mail gewerkt kan worden:
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers = $headers . 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
//from-header:
$headers = $headers . 'From: Voornaam Achternaam <verzender@domain.tld>';
//overige mail-gerelateerde zaken
$to = 'ontvanger@domain.tld';
$subject = 'onderwerp van dit bericht';
//bericht in HTML opgemaakt:
$message = '<html><body>
<b>Beste ontvanger</b>,<br><br>
Dit is mijn eerste mailtje dat ik via PHP verstuur!
</body></html>';
//verzend het bericht:
mail($to, $subject, $message, $headers);
De eerste header geeft aan dat het bericht gebruik maakt van de Multipurpose Internet Mail Extensions (MIME). Dit is een toevoeging aan de oorspronkelijke e-mail standaard die toestaat HTML in emailberichten te gebruiken. De tweede header geeft aan dat de inhoud een combinatie van tekst en HTML is en geeft tevens aan welke karakterset is gebruikt. Naar keuze kan hier ook voor een andere karakterset worden gekozen, zoals UTF-8. De derde header is de gebruikelijke From:-header.
De verschillende onderdelen van de headers worden aan elkaar geknoopt door middel van punten (zie hoofdstuk 2). De drie headers worden gescheiden door een CRLF, ofwel "\r\n".
Het te verzenden e-mailbericht bevat het bericht in HTML formaat met alle bijbehorende tags.
Opmerkingen
Let er bij het verzenden van HTML e-mail op dat veel clients slechts een subset van de volledige HTML specificatie ondersteunen. Meer geavanceerde onderdelen van HTML worden in sommige clients dan ook niet of verkeerd weergegeven.
Pas tevens op met CSS, waarvoor de ondersteuning vaak nog slechter is dan HTML.
De PHP functie mail()
is niet geschikt om grote hoeveelheden e-mail achter elkaar te verzenden. De reden hiervoor is dat iedere keer dat de functie wordt aangeroepen een nieuwe verbinding met de mailserver wordt opgezet. Voor grote hoeveelheden email zoals nieuwsbrieven en mailinglijsten is het vele malen efficiënter als de verbinding met de mailserver in stand wordt gehouden totdat alle berichten verzonden zijn.
Als alternatief voor mail()
kan de open source programmatuur PHPMailer gebruikt worden. Voor middelgrote mailinglijsten kan PHPMailer gebruik maken van Sendmail (vermits dit op de webserver is geconfigureerd). Voor grote mailinglijsten kan PHPMailer gebruikt worden om direct aan een SMTP mailserver aan te koppelen. Voor meer informatie over PHPMailer zie https://github.com/PHPMailer/PHPMailer#readme.
Tot slot moet worden opgemerkt dat bij het gebruik van XAMPP of een soortgelijk pakket op de eigen computer de instellingen niet goed staan om mails te kunnen verzenden. Dit leidt of tot een foutmelding of er wordt simpelweg geen mail verzonden. Test een mailscript dus altijd op je webhost.
Praktijkvoorbeeld: e-mailformulier
In dit voorbeeld wordt een eenvoudig mailformulier behandeld. Dit formulier bestaat uit een HTML-gedeelte waar de bezoeker van de website enige gegevens kan invullen en een PHP-gedeelte dat de daadwerkelijke verzending op zich neemt.
Laten we beginnen met het HTML-gedeelte. Dit eenvoudige formulier bestaat uit drie velden waarin de bezoeker naam, e-mailadres en bericht kan invullen:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Contact</title>
</head>
<body>
<h1>Contact</h1>
<form action="contact.php" method="post">
<table border="0">
<tr>
<td>Naam:</td>
<td><input type="text" name="naam"></td>
</tr>
<tr>
<td>Email:</td>
<td><input type="text" name="email"></td>
</tr>
<tr>
<td>Bericht:</td>
<td><textarea name="bericht" rows="5" cols="20"></textarea></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="Verzenden"></td>
</tr>
</table>
</form>
</body>
</html>
Het formulier wordt opgeslagen als contact.php. Zoals uit de form-action blijkt wordt bij verzenden het formulier dus naar zichzelf verstuurd. Hiermee is het mogelijk om formulier en verzendscript in één bestand bij elkaar te houden. Het bij elkaar houden van formulier en script maakt het makkelijker om later een gebruiksvriendelijke formuliercontrole toe te voegen. Overigens mag de form-action in dit geval ook weggelaten worden.
Verzendscript
Voor dit eenvoudige formulier heeft het niet zo veel nut om van HTML e-mail gebruik te maken. Het verzendscript kan er dan als volgt uit zien:
$ontvanger = 'je_eigen_em@iladres.tld';
$onderwerp = 'Emailformulier PHPBoek';
//stel bericht op
$bericht = 'Naam: '.$_POST['naam'].'
Email: '.$_POST['email'].'
Bericht: '.$_POST['bericht'];
//stel verzend-header op
$verzender = 'From: '.$_POST['naam'].' <'.$_POST['email'].'>';
//verzend bericht
if (mail($ontvanger, $onderwerp, $bericht, $verzender)) {
//succesmelding als correct verzonden
echo '<p>Bericht is succesvol verzonden.</p>';
}
else {
//foutmelding als niet verzonden
echo '<p>Er is een fout opgetreden bij het verzenden van het bericht. Probeer het later nogmaals.</p>';
}
Allereerst worden ontvanger en onderwerp vastgelegd. Het bericht wordt vervolgens samengesteld uit de gegevens van het formulier. De From:-header wordt eveneens samengesteld uit gegevens van het formulier. Dit alles wordt vervolgens gebruikt in mail()
om het bericht te verzenden.
Formulier en script samenvoegen
Het script moet nu nog aan het formulier worden toegevoegd. De functie empty()
uit hoofdstuk 8 kan ook hier weer gebruikt worden om te bepalen of het formulier verzonden is of niet. Indien $_POST
leeg is, is het formulier niet verzonden en moet het formulier worden weergegeven. Bestaat $_POST
wel, dan is er iets ingevuld en kan een e-mail worden verzonden.
Samengevoegd kan het mailscript er dus als volgt uit zien:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Contact</title>
</head>
<body>
<h1>Contact</h1>
<?php
if (empty($_POST)) {
//formulier niet verzonden, geef formulier weer
?>
<form action="contact.php" method="post">
<table border="0">
<tr>
<td>Naam:</td>
<td><input type="text" name="naam"></td>
</tr>
<tr>
<td>Email:</td>
<td><input type="text" name="email"></td>
</tr>
<tr>
<td>Bericht:</td>
<td><textarea name="bericht" rows="5" cols="20"></textarea></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="Verzenden"></td>
</tr>
</table>
</form>
<?php
}
else {
//formulier wel verzonden, verzend bericht
//definieer verzendopties
$ontvanger = 'je_eigen_em@iladres.tld';
$onderwerp = 'Emailformulier PHPBoek';
//stel bericht op
$bericht = 'Naam: '.$_POST['naam'].'
Email: '.$_POST['email'].'
Bericht: '.$_POST['bericht'];
//stel verzend-header op
$verzender = 'From: '.$_POST['naam'].' <'.$_POST['email'].'>';
//verzend bericht
if (mail($ontvanger, $onderwerp, $bericht, $verzender)) {
//succesmelding als correct verzonden
echo '<p>Bericht is succesvol verzonden.</p>';
}
else {
//foutmelding als niet verzonden
echo '<p>Er is een fout opgetreden bij het verzenden van het bericht. Probeer het later nogmaals.</p>';
}
}
?>
</body>
</html>
Zelftest
- Er is één header verplicht bij het gebruik van
mail()
. Welke?- Een header die aangeeft of het bericht in HTML of plaintext is.
- Een header die aangeeft welke karakterset is gebruikt.
- Een header die aangeeft wie de ontvanger van het bericht is.
- Een header die aangeeft wie de afzender van het bericht is.
- Welke van de onderstaande stelling(en) is/zijn waar?
Imail()
kan controleren of een bericht verzonden is.
IImail()
kan controleren of een bericht aangekomen is.- Alleen stelling I is waar.
- Alleen stelling II is waar.
- Beide stellingen zijn waar.
- Beide stellingen zijn onwaar.
- Meerdere e-mail headers worden gescheiden door…
- … een spatie.
- … een CRLF.
- … een komma.
- … een \n\r.
- Welke van onderstaande stelling(en) is/zijn waar?
I Het is geen enkel probleem om CSS in HTML e-mails te gebruiken.
IImail()
kan zonder problemen gebruikt worden voor het verzenden van grote hoeveelheden e-mail.- Alleen stelling I is waar.
- Alleen stelling II is waar.
- Beide stellingen zijn waar.
- Beide stellingen zijn onwaar.
- Waarom is het handig om formulier en script in één bestand te hebben?
- Script en formulier raken zo niet kwijt.
- Het is niet mogelijk om een formulier en script over twee bestanden te splitsen.
- Het is eenvoudiger om een foutcontrole toe te voegen.
Antwoorden
- d
- a
- b
- d
- c
Oefening: e-mailformulier met foutcontrole
Opdracht 1
Maak een mailformulier waarbij de bezoeker gevraagd wordt om naam, e-mailadres, adresgegevens en een bericht in te vullen. Beslis zelf welke velden hiervoor noodzakelijk zijn en hoe deze velden in het formulier worden weergegeven.
Een druk op de verzendknop zorgt ervoor dat het formulier in HTML-formaat wordt verzonden. Gebruik een tabel om de gegevens overzichtelijk in de e-mail weer te geven.
Opdracht 2
Voeg een foutcontrole toe aan het zojuist gemaakte formulier. Hierbij kan de theorie uit hoofdstuk 8 worden gebruikt. Naam, e-mailadres en bericht zijn verplichte velden. De overige velden zijn niet verplicht.
Uitwerking
opdracht1.php
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Contact</title>
</head>
<body>
<h1>Contact</h1>
<?php
if (empty($_POST)) {
//formulier niet verzonden, geef formulier weer
?>
<form method="post">
<table border="0">
<tr>
<td>Naam:</td>
<td><input type="text" name="naam"></td>
</tr>
<tr>
<td>Email:</td>
<td><input type="text" name="email"></td>
</tr>
<tr>
<td>Straat en huisnummer:</td>
<td><input type="text" name="straat"></td>
</tr>
<tr>
<td>Postcode en plaats:</td>
<td><input type="text" name="plaats"></td>
</tr>
<tr>
<td>Bericht:</td>
<td><textarea name="bericht" rows="5" cols="20"></textarea></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="Verzenden"></td>
</tr>
</table>
</form>
<?php
}
else {
//formulier wel verzonden, verzend bericht
//headers voor html-mail:
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers = $headers . 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
//from-header:
$headers = $headers . 'From: '.$_POST['naam'].' <'.$_POST['email'].'>';
//overige mail-gerelateerde zaken
$ontvanger = 'je_eigen_em@iladres.tld';
$onderwerp = 'Emailformulier PHPBoek';
//bericht in HTML opgemaakt:
$bericht = '<html><body>
<table border="0">
<tr>
<td>Naam:</td>
<td>'.htmlspecialchars($_POST['naam']).'</td>
</tr>
<tr>
<td>Email:</td>
<td>'.htmlspecialchars($_POST['email']).'</td>
</tr>
<tr>
<td>Straat en huisnummer:</td>
<td>'.htmlspecialchars($_POST['straat']).'</td>
</tr>
<tr>
<td>Postcode en plaats:</td>
<td>'.htmlspecialchars($_POST['plaats']).'</td>
</tr>
<tr>
<td>Bericht:</td>
<td>'.htmlspecialchars($_POST['bericht']).'</td>
</tr>
</table>
</body></html>';
//verzend bericht
if (mail($ontvanger, $onderwerp, $bericht, $headers)) {
//succesmelding als correct verzonden
echo '<p>Bericht is succesvol verzonden.</p>';
}
else {
//foutmelding als niet verzonden
echo '<p>Er is een fout opgetreden bij het verzenden van het bericht. Probeer het later nogmaals.</p>';
}
}
?>
</body>
</html>
opdracht2.php
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Contact</title>
</head>
<body>
<h1>Contact</h1>
<?php
//let op: het verzendgedeelte moet nu eerst, om te controleren of het formulier goed is ingevuld
if (!empty($_POST)) {
//formulier wel verzonden, controleer velden
if (empty($_POST['naam'])) $veldfout['naam'] = TRUE;
if (empty($_POST['email'])) $veldfout['email'] = TRUE;
if (empty($_POST['bericht'])) $veldfout['bericht'] = TRUE;
//velden ok, verzend bericht
if (!isset($veldfout)) {
//headers voor html-mail:
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers = $headers . 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
//from-header:
$headers = $headers . 'From: '.$_POST['naam'].' <'.$_POST['email'].'>';
//overige mail-gerelateerde zaken
$ontvanger = 'je_eigen_em@iladres.tld';
$onderwerp = 'Emailformulier PHPBoek';
//bericht in HTML opgemaakt:
$bericht = '<html><body>
<table border="0">
<tr>
<td>Naam:</td>
<td>'.htmlspecialchars($_POST['naam']).'</td>
</tr>
<tr>
<td>Email:</td>
<td>'.htmlspecialchars($_POST['email']).'</td>
</tr>
<tr>
<td>Straat en huisnummer:</td>
<td>'.htmlspecialchars($_POST['straat']).'</td>
</tr>
<tr>
<td>Postcode en plaats:</td>
<td>'.htmlspecialchars($_POST['plaats']).'</td>
</tr>
<tr>
<td>Bericht:</td>
<td>'.htmlspecialchars($_POST['bericht']).'</td>
</tr>
</table>
</body></html>';
//verzend bericht
if (mail($ontvanger, $onderwerp, $bericht, $headers)) {
//succesmelding als correct verzonden
$verzonden = TRUE;
}
else {
//foutmelding als niet verzonden
$nietverzonden = TRUE;
}
}
}
if ($verzonden == TRUE) {
echo '<p>Bericht is succesvol verzonden.</p>';
}
else {
//formulier niet verzonden, geef formulier weer
if ($nietverzonden == TRUE) {
echo '<p>Er is een fout opgetreden bij het verzenden van het bericht. Probeer het later nogmaals.</p>';
}
?>
<form method="post">
<table border="0">
<tr>
<td>Naam:</td>
<td><?php if ($veldfout['naam'] == TRUE) {
echo '<p>Het veld naam is verplicht.</p>';
} ?>
<input type="text" name="naam" value="<?php echo htmlspecialchars($_POST['naam']); ?>"></td>
</tr>
<tr>
<td>Email:</td>
<td><?php if ($veldfout['email'] == TRUE) {
echo '<p>Het email naam is verplicht.</p>';
} ?>
<input type="text" name="email" value="<?php echo htmlspecialchars($_POST['email']); ?>"></td>
</tr>
<tr>
<td>Straat en huisnummer:</td>
<td><input type="text" name="straat" value="<?php echo htmlspecialchars($_POST['straat']); ?>"></td>
</tr>
<tr>
<td>Postcode en plaats:</td>
<td><input type="text" name="plaats" value="<?php echo htmlspecialchars($_POST['plaats']); ?>"></td>
</tr>
<tr>
<td>Bericht:</td>
<td><?php if ($veldfout['bericht'] == TRUE) {
echo '<p>Het veld bericht is verplicht.</p>';
} ?>
<textarea name="bericht" rows="5" cols="20"><?php echo htmlspecialchars($_POST['bericht']); ?></textarea></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="Verzenden"></td>
</tr>
</table>
</form>
<?php
}
?>
</body>
</html>