Envoyer un mail en PHP
Date de publication : 1/07/2007
Par
Adrien Pellegrini (Page d'accueil)
Josselin Willette (Page d'accueil)
Envoyer un mail en PHP n'est pas une tâche bien difficile.
Personnaliser son mail et comprendre le fonctionnement des différents
entêtes est bien plus compliqué.
1. Introduction
1.1. Remerciements
1.2. Préambule
2. Les entêtes (headers)
Bcc
Cc
Content-Description
Content-Type
Content-Transfer-Encoding
Date
From
MIME-Version
Priority
Reply-To
Sender
Subject
To
X-Confirm-Reading-To
X-Mailer
X-Priority
3. Mise en pratique
3.1. Mail de base
3.2. Spécifier un expéditeur différent
3.3. Mail format HTML
3.4. Mail simple avec pièce jointe
3.5. Mail complet (HTML + pièces jointes)
4. Créer un formulaire de contact simple
4.1. Formulaire HTML
4.2. Récupération des informations et envoi du mail
4.3. Sécurité
4.4. Vérification des champs de formulaire
4.5. Récapitulatif
5. Quelques liens
1. Introduction
1.1. Remerciements
1.2. Préambule
La fonction mail() que je vais utiliser pour envoyer
des mails ne requiert aucune installation. Elle est présente
automatiquement dans les versions de PHP.
Toutefois il vous faut configurer le serveur SMTP qui permet
d'envoyer des mails. Pour le configurer vous devez trouver
deux lignes dans le fichier php.ini de votre serveur.
Ces deux lignes sont :
SMTP "localhost"
smtp_port "25"
|
Une fois votre server SMTP configuré, vous êtes prêt pour
lire la suite de cet article.
2. Les entêtes (headers)
Les entêtes doivent, en théorie, être séparés par un CRLF (\r\n).
Toutefois, il se peut qu'il y ait des webmail comme Gmail avec qui
le CRLF ne marche pas. Il devra être remplacé par un LF (\n).
Bcc
Bcc, pour "Blind carbon copy", sert à lister les destinataires comme To et
Cc à la différence que chaque destinataire ne saura pas qui se trouve sur
la liste des destinataires.
Bcc: adresse@developpez.com
|
Cc
Cc, pour "Carbon copy", sert à lister les destinataires comme To et
Bcc à la différence que chaque destinataire saura qui se trouve sur la
liste des destinataires.
Cc: adresse@developpez.com
|
Content-Description
Content-Description est utilisé pour donner une description
d'une partie d'un mail.
Par exemple pour une image.
Content-Type
Content-Type définit le type du contenu du message.
Généralement composé d'un type/sous-type.
Le type par défaut est "Content-type: text/plain; charset=us-ascii".
text/plain :
Plain Text n'est utilisé que pour envoyer une séquence de
caractères non formatés.
Plain Text peut être complété avec un
charset pour
définir le jeu de caractères. S'il n'est pas spécifié,
celui par défaut sera utilisé (US-ASCII).
multipart :
Le type multipart requiert un paramètre appelé
boundary.
Ce paramètre est une sorte de limite entre les différentes
parties d'un mail au format multipart. Il existe plusieurs
sous-types que voici :
multipart/mixed :
Ce type est utilisé pour les messages comportant plusieurs
parties indépendantes les unes des autres. Le type par
défaut est "text/plain".
multipart/alternative :
Ce type est utilisé pour spécifier une version différente
à une même partie de message. Le client mail choisira
alors la meilleure version pour lui. La version préférée
est généralement placée à la fin.
multipart/digest :
Ce type est identique au "multipart/mixed" mais a comme
type par défaut "message/rfc822" qui est le plus compatible
avec la norme
RFC934.
image :
Ce type est utilisé pour indiquer que le message contient
une image.
Quelques sous-types : image/jpeg, image/gif, image/png. [
*]
audio :
Ce type est utilisé pour indiquer que le message contient
une donnée audio.
Quelques sous-types : audio/ac3, audio/mp4. [
*]
video :
Ce type est utilisé pour indiquer que le message contient
une donnée vidéo.
Quelques sous-types : video/mpeg. [
*]
application :
Ce type est utilisé dans le cas où il n'y en a pas d'autre.
application/octet-stream :
Ce type sert à indiquer que le message contient des
données au format binaire.
application/postscript :
Ce type indique un programme PostScript.
Content-Transfer-Encoding
Content-Transfer-Encoding spécifie le type d'encodage.
Encodages possibles : 7bit, 8bit, binary, quoted-printable,
base64, ietf-token, x-token.
Date
Date spécifie une date pour le message.
Cette date devra être au format suivant :
"les 3 premiers caractères du jour (Sun - Sat)" "date (1-31)"
"les 3 premiers caractères du mois (Jan - Dec)" "année (2006)"
"heure format 24h (hh:mm:ss)" "fuseau horaire (GMT)"
Date: Sun, 17 Sep 2006 09:33:12 GMT
|
| Code permettant d'avoir le bon format avec la fonction date() |
|
From
From contient l'adresse mail de l'expéditeur.
From: "Moi" moi@developpez.com
|
MIME-Version
MIME-Version spécifie qu'on utilise le format MIME et sa version.
Priority
Priority spécifie la priorité du mail. Il en existe 3 : "normal", "urgent" et
"non-urgent".
Reply-To
Reply-to spécifie une adresse autre que celle de
l'expéditeur pour que le destinataire renvoie sa réponse à
celle-là et pas celle du From.
Reply-To: autre@developpez.com
|
Sender
Sender spécifie l'authentique auteur du mail. Sender sera
utilisé par exemple si celui qui envoie le mail n'est pas
celui qui l'a écrit.
Sender: auteur@developpez.com
|
Subject
Subject spécifie le "titre" du message.
Subject: Mail de confirmation
|
To
To spécifie le premier destinataire.
To: "Destinataire" destinataire@developpez.com
|
To: Destinataire <destinataire@developpez.com>
|
To: <destinataire@developpez.com>
|
To: destinataire@developpez.com
|
X-Confirm-Reading-To
X-Confirm-Reading-To envoie un mail pour spécifier si le message
a été reçu ou lu. Les clients de messagerie demandent
habituellement si l'accusé peut être envoyé.
X-Confirm-Reading-To: adresse@developpez.com
|
X-Mailer
X-Mailer spécifie le logiciel d'envoi du mail.
X-Priority
X-Priority spécifie la priorité du mail.
3. Mise en pratique
 |
Normalement la norme spécifie qu'il faut séparer les entêtes par
un CRLF (\r\n). Cependant, certaines boîtes mail utilisent seulement
un LF (\n). Donc si vous ne recevez pas votre mail essayez avec un LF.
|
3.1. Mail de base
Simple mail avec un peu de texte.
Inconvénient : si vous envoyez ce mail depuis votre
site web, vous allez voir apparaître dans l'expéditeur quelque
chose comme
"CGI-Mailer <cgi-mailer@server.com>"
$to = 'truc@server.com';
$subject = 'Developpez.com - Test Mail';
$msg = 'Developpez.com - Message du mail ...';
mail($to, $subject, $msg);
|
3.2. Spécifier un expéditeur différent
Pour résoudre l'inconvénient précédent, il faut utiliser
l'entête "From".
Cet exemple montre aussi comment utiliser l'entête Bcc.
$to = 'truc@server.com';
$subject = 'Developpez.com - Test Mail';
$msg = 'Developpez.com - Message du mail ...';
$headers = 'From: Adrien Pellegrini <mail@server.com>'."\r\n";
$headers .= 'Bcc: Moi <moi@server.com>; lui <lui@server2.com>'."\r\n";
$headers .= "\r\n";
mail($to, $subject, $msg, $headers);
|
3.3. Mail format HTML
La plupart des clients mail comme Gmail, Hotmail, Yahoo Mail,
ont une réglementation assez stricte au niveau du contenu du
message.
Par exemple, il est inutile d'utiliser les balises
<head>, <body>, <link>, <style> car elles seront
automatiquement supprimées dans la plupart des cas.
Donc il n'est pas question de définir une feuille de style
externe. Pour cela il faudra utiliser l'attribut style
des balises.
Il faut savoir aussi que toutes les propriétés du CSS ne sont
pas prises en compte.
Pour avoir un mail le plus compatible possible, il vous faudra
donc copier simplement le contenu de la balise <body>
en utilisant le CSS dans les balises.
$to = 'truc@server.com';
$subject = 'Developpez.com - Test Mail';
$headers = 'Mime-Version: 1.0'."\r\n";
$headers .= 'Content-type: text/html; charset=utf-8'."\r\n";
$headers .= "\r\n";
$msg = '<strong>Developpez.com</strong> - Message du mail ...';
mail($to, $subject, $msg, $headers);
|
3.4. Mail simple avec pièce jointe
Pour envoyer un mail avec une pièce jointe, il faut utiliser
le Content-Type: multipart/mixed.
Tous les types "multipart" requièrent un paramètre appelé
boundary.
Ce paramètre est une sorte de limite entre les différentes
parties d'un mail (ici, le texte du mail et la pièce jointe).
Le
boundary commence par 2 tirets (--) et termine
par un CRLF. Le
boundary doit être compris entre 1
et 70 caractères.
Les
2 tirets au début
sont obligatoires pour des
raisons de compatibilité avec une ancienne norme qui est
la
RFC934.
Le boundary est généralement une chaîne aléatoire.
$to = 'truc@server.com';
$subject = 'Developpez.com - Test Mail';
$boundary = md5(uniqid(microtime(), TRUE));
$headers = 'From: Adrien Pellegrini <mail@server.com>'."\r\n";
$headers .= 'Mime-Version: 1.0'."\r\n";
$headers .= 'Content-Type: multipart/mixed;boundary='.$boundary."\r\n";
$headers .= "\r\n";
$msg = 'This is a multipart/mixed message.'."\r\n\r\n";
$msg .= '--'.$boundary."\r\n";
$msg .= 'Content-type:text/plain;charset=utf-8'."\r\n";
$msg .= 'Content-transfer-encoding:8bit'."\r\n";
$msg .= 'Un message avec une pièce jointe.'."\r\n";
$file_name = 'image.jpg';
if (file_exists($file_name))
{
$file_type = filetype($file_name);
$file_size = filesize($file_name);
$handle = fopen($file_name, 'r') or die('File '.$file_name.'can t be open');
$content = fread($handle, $file_size);
$content = chunk_split(base64_encode($content));
$f = fclose($handle);
$msg .= '--'.$boundary."\r\n";
$msg .= 'Content-type:'.$file_type.';name='.$file_name."\r\n";
$msg .= 'Content-transfer-encoding:base64'."\r\n";
$msg .= $content."\r\n";
}
$msg .= '--'.$boundary."\r\n";
mail($to, $subject, $msg, $headers);
|
3.5. Mail complet (HTML + pièces jointes)
Remarque : Si vous voulez mettre des images dans le mail,
il faut mettre le chemin absolu de l'image et non son chemin
relatif.
$to = 'truc@serveur.com';
$subject = 'Developpez.com - Test Mail';
$boundary = md5(uniqid(microtime(), TRUE));
$headers = 'From: Adrien Pellegrini <mail@server.com>'."\r\n";
$headers .= 'Mime-Version: 1.0'."\r\n";
$headers .= 'Content-Type: multipart/mixed;boundary='.$boundary."\r\n";
$headers .= "\r\n";
$msg = 'Texte affiché par des clients mail ne supportant pas le type MIME.'."\r\n\r\n";
$msg .= '--'.$boundary."\r\n";
$msg .= 'Content-type: text/html; charset=utf-8'."\r\n\r\n";
$msg .= '
<div style="padding:5px; width:600px; background-color:#E0EBF5; border:#000000 thin solid">
<div>
<img src="http://www.site.com/header.png" alt="Developpez.com - Newsletter" />
</div>
<div>
<h2 style="color:#274E9C; text-decoration:underline">Section :</h2>
<ul>
<li><a href="#devweb">Développement Web</a></li>
<li><a href="#php">PHP</a></li>
</ul>
</div>
<div>
<h2 id="devweb" style="color:#274E9C; text-decoration:underline">
Développement Web :
</h2>
<ul>
<li>Comment personnaliser une fenêtre Apollo, par <em>Olivier Bugalotto</em></li>
<li>Présentation du langage XHTML, par <em>Adrien Pellegrini</em></li>
<li>Initiation au protocole SMTP et exemple d application en langage C,
par <em>Benjamin Roux</em></li>
<li>Modification inline de données en utilisant
des classes Javascript, par <em>Olivier Lance</em></li>
</ul>
</div>
<div>
<h2 id="php" style="color:#274E9C; text-decoration:underline">PHP :</h2>
<ul>
<li>Débuter avec le Zend Framework en PHP (approche MVC),
cours de Rob Allen traduit par <em>Guillaume Rossolini</em></li>
<li>Simplifiez les accès à votre base de données avec EZPDO en PHP,
par <em>Pierre-Nicolas Mougel</em></li>
<li>Chiffrement et hash en PHP contre l attaque Man in the middle,
par <em>Guillaume Affringue</em></li>
<li>La sécurité dans les expressions régulières en PHP,
par <em>Guillaume Rossolini</em></li>
</ul>
</div>
</div>'."\r\n";
$file_name = 'image.jpg';
if (file_exists($file_name))
{
$file_type = filetype($file_name);
$file_size = filesize($file_name);
$handle = fopen($file_name, 'r') or die('File '.$file_name.'can t be open');
$content = fread($handle, $file_size);
$content = chunk_split(base64_encode($content));
$f = fclose($handle);
$msg .= '--'.$boundary."\r\n";
$msg .= 'Content-type:'.$file_type.';name='.$file_name."\r\n";
$msg .= 'Content-transfer-encoding:base64'."\r\n\r\n";
$msg .= $content."\r\n";
}
$file_name = 'image2.jpg';
if (file_exists($file_name))
{
$file_type = filetype($file_name);
$file_size = filesize($file_name);
$handle = fopen($file_name, 'r') or die('File '.$file_name.'can t be open');
$content = fread($handle, $file_size);
$content = chunk_split(base64_encode($content));
$f = fclose($handle);
$msg .= '--'.$boundary."\r\n";
$msg .= 'Content-type:'.$file_type.';name='.$file_name."\r\n";
$msg .= 'Content-transfer-encoding:base64'."\r\n\r\n";
$msg .= $content."\r\n";
}
$msg .= '--'.$boundary."\r\n";
mail($to, $subject, $msg, $headers);
|
4. Créer un formulaire de contact simple
Vous avez envie d'intégrer un formulaire de contact sur votre site
Web mais éviter d'utiliser mailto qui ouvre le logiciel de messagerie
de vos visiteurs ?
Cette partie va vous montrer comment créer un formulaire de contact
qui vous envoie un e-mail de façon transparente pour l'utilisateur.
4.1. Formulaire HTML
Nous allons commencer par créer un formulaire HTML qui
comprendra les champs :
- civilité
- nom/prénom
- adresse e-mail
- sujet
- message
Voici ce que ça donne :
<form action="send_email.php" method="post">
<p>
<label for="civilite">Civilité :</label>
<select id="civilite" name="civilite">
<option value="mr" selected="selected">Monsieur</option>
<option value="mme">Madame</option>
<option value="mlle">Mademoiselle</option>
</select>
</p>
<p>
<label for="nom">Nom/Prénom :</label>
<input type="text" id="nom" name="nom" />
</p>
<p>
<label for="email">E-mail :</label>
<input type="text" id="email" name="email" />
</p>
<p>
<label for="sujet">Sujet :</label>
<input type="text" id="sujet" name="sujet" />
</p>
<p>
<label for="message">Message :</label>
<textarea id="message" name="message" cols="40" rows="4"></textarea>
</p>
<p>
<input type="submit
|