Formulaire de contact avec PHPMailer
|Introduction
Le formulaire de contact est le premier et le plus simple moyen de communication entre un client et le propriétaire du site. Que ce soit sur un blog pour demander un article à l’administrateur ou sur un site professionnel pour demander un devis, le formulaire de contact se doit d’être simple à remplir et surtout sécurisé pour pouvoir faire le tri entre clients et spams.
Dans cet article nous mettrons en place un formulaire très simple : nom, prénom, @mail, sujet, message. Nous y mettrons un peu d’AJAX pour le rendre plus réactif. La vérification des champs sera très simple : syntaxe mail pour le champ @mail et vérification des caractères [a-z._-] pour les autres champs. Ce qui nous assurera un formulaire sécurisé au niveau des injections de la fonction mail().
En ce qui concerne l’envoi lui-même du mail je vous conseillerai d’utiliser la classe PHPMailer qui fourni vraiment tout ce qui est nécessaire pour envoyer un mail sans se casser la tête à rédiger les entêtes ou joindre des fichiers.
Nous finirons par mettre en place un peu de sécurité contre le spam du formulaire.
Création du formulaire
Créez un formulaire tout bête avec 4 input text et un textarea :
<form id="form_contact" action="contact.php" method="post"> <fieldset> <legend>Contactez-nous</legend> <label>Nom</label> <input type="text" name="nom" value=""/> <div class="clearer"></div> <label>Prénom</label> <input type="text" name="prenom" value=""/> <div class="clearer"></div> <label>@mail</label> <input type="text" name="mail" value=""/> <div class="clearer"></div> <label>Sujet</label> <input type="text" name="sujet" value=""/> <div class="clearer"></div> <label>Message</label> <textarea name="message" cols="45" rows="6"></textarea> <div class="clearer"></div> <label> </label> <input type="submit" value="envoyer"/> <div class="clearer"></div> <div id="result_contact"></div> </fieldset> </form>
Je l’ai mis un peu en forme grâce à des LABEL et à des DIV de classe « clearer » que j’ai défini dans le style :
.clearer{clear:both;} legend{font-size:1.3em;} fieldset{float:left;width:40%;} a{color:#0000FF;} label{float:left;width:120px;} input{width:200px;}
Mise en place de l’AJAX
Créons d’abord la fonction qui va capturer l’envoi du formulaire puis le stopper afin de nous laisser la main pour traiter l’envoi nous-même :
document.addEvent('domready', function(){ $('form_contact').addEvent('submit', function(e){ e.stop(); /* Ici on enverra le formulaire nous-même */ }); });
On prépare la requête AJAX en définissant les fonctions à exécuter en cas de réussite, échec, réponse, et lors de l’envoi :
var button = this.getElement('input[type=submit]'); this.set('send', { onRequest: function(){ button.morph({opacity:0}); $('result_contact').set('html',''); }, onComplete: function(){ button.morph({opacity:1}); }, onSuccess: function(responseText, responseXML){ // On définira en dessous ce qui se passe ici }, onFailure: function(xhr){ button.morph({opacity:1}); $('result_contact').set('html','Erreur lors de la communication avec le serveur.'); } });
Traitement du XML
Maintenant attaquons nous à la lecture de la réponse du serveur. Pour mon exemple j’ai choisi d’utiliser le XML qui nous permettra de recevoir des données uniquement et de définir nous même quelle mise en forme utiliser.
Le fichier suivant nous montre quel genre de XML nous traiterons et comment l’utiliser :
<?xml version="1.0" encoding="UTF-8"?> <root> <error>no</error> <uneliste> <item>blah</item> <item>bleh</item> <item>blih</item> </uneliste> </root>
Pour trouver « no » qui se trouve dans <error> il faut utiliser le code ci-dessous :
var error = $(responseXML).getElement('root error').get('text');
Pour traiter tous les <item>, utiliser la méthode « each » fournit par Mootools :
$(responseXML).getElements('root uneliste item').each(function(element){ // Faites le traitement ici }
Maintenant utilisons le code qui suit pour traiter la réponse du serveur.
onSuccess: function(responseText, responseXML){ var type = $(responseXML).getElement('root error').get('text'); switch(type){ case 'field': $('result_contact').set('html','Les champs ci-dessous sont mal remplis.'); $(responseXML).getElements('root fields field').each(function(el){ $('result_contact').adopt(new Element('div', {html:el.get('text')})); }); break; case 'envoi': $('result_contact').set('html','Problème lors de l\'envoi avec PHPMailer.<br/>'); $('result_contact').adopt(new Element('div', {html:$(responseXML).getElements('root exception').get('text')})); break; case 'time': var secondes = $(responseXML).getElements('root seconds').get('text'); $('result_contact').set('html','Vous devez attendre '+secondes+' secondes avant d\'enoyer un nouveau message.'); break; case 'session': $('result_contact').set('html','Votre navigateur n\'est pas compatible avec les sessions.'); break; case 'no': $('result_contact').set('html','Message envoyé.'); break; default: $('result_contact').set('html','Erreur de type inconnu.'); break; } }
Analyse du formulaire
Par défaut nous mettrons la variable $type (qui défini le type d’erreur) à ‘no’ qui indique qu’aucune erreur n’est apparu lors du traitement.
Pour vérifier qu’un champ ne contienne que les caractères autorisés, utilisez le code ci-dessous. Il n’autorise que les lettres ainsi que les ._- mais ca permet de limiter un maximum les tentatives de fraudes. Si vous voulez autoriser plus que ça, c’est tout à fait autorisé. Mais interdisez à tout pris les saut de lignes, ce sont les plus dangereus pour les injections mail().
if(!preg_match('#^[a-z._-]+$#i', $_POST['nom'])){$fields[] = 'Nom'; $type='field';}
Et pour vérifier l’adresse électronique vous pouvez utiliser l’expression régulière ci-dessous :
if(!preg_match('#^[a-zA-Z0-9]+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$#', $_POST['mail'])) {$fields[] = '@mail'; $type='field';}
Envoi du mail
Une fois tous les champs vérifiés, nous pouvons procéder à l’envoi du mail. Comme je vous l’expliquai dans l’introduction de ce chapitre, nous allons utiliser une classe PHP qui est très facile à installer et à utiliser. Vous n’avez besoin d’inclure qu’un seul fichier dans votre code pour pouvoir l’utiliser.
include_once 'phpmailer.class.php';
Nous pouvons maintenant crée un objet PHPMailer puis l’utiliser :
try{ $mailer->AddAddress(YOUR_MAIL, YOU); $mailer->AddReplyTo($_POST['mail'], $_POST['prenom'].' '.$_POST['nom']); $mailer->SetFrom($_POST['mail'], $_POST['prenom'].' '.$_POST['nom']); $mailer->Subject = $_POST['sujet']; $mailer->AltBody = 'Votre client mail n\'est pas compatible HTML.'; $mailer->MsgHTML($_POST['message']); $mailer->Send(); }catch(phpmailerException $e){ $type = 'envoi'; }
Sécurité contre le spam
Pour se protéger contre le spam il existe 2 techniques : vérifier que la personne qui rempli le formulaire n’est pas un robot et limiter la fréquence d’envoi des mails.
Se protéger des robots
Pour se protéger contre les robots il faut forcer l’utilisateur à faire une action qui ne pourrait pas être faite par un robot (ou peu de robots). Je vous proposerai aujourd’hui de faire copier un texte contenu dans une image. Peu de robots en sont capables pour le moment.
Vous avez la possibilité d’utiliser d’autres techniques :
mathématiques -> (3 x 4 + 5) = ?
logique -> 1 3 5 7 ?
générale -> en quelle année a eu lieu la prise de la bastille ?
Pour réaliser cette protection je vous conseillerai d’utiliser le même générateur de captcha que moi, il est hyper simple à utiliser.
Dans votre formulaire ajoutez les lignes suivantes pour faire apparaitre l’image à copier.
<img src="img-captcha.php"/> <input type="text" name="capa"/>
Lors de l’envoi du formulaire, vérifiez que le code copié soit correct. Le deuxième paramètre de la méthodes rends la vérification insensible à la casse.
if( PhpCaptcha::Validate($_POST['capa'], true) ){ //true }
Créez maintenant le fichier img-captacha.php :
<?php ini_set('display_errors','0'); include_once 'captcha.class.php'; $fonts = array('arial.ttf'); $captcha = new PhpCaptcha($fonts, 180, 40); $captcha->Create(); ?>
La première ligne du code ci-dessus permet de ne pas afficher les erreurs et d’afficher dans tous les cas un image valide.
Limiter la fréquence
Pour limiter la fréquence d’utilisation du formulaire de contact, nous allons utiliser la session. Tout d’abord, pour s’assurer que le navigateur mémorise bien les sessions, avant d’afficher le formulaire il faut stocker une valeur en session :
$_SESSION['use_session'] = 'yes';
Après l’envoi du mail, il faut créer une variable en session qui mémorisera la date de l’envoi du dernier mail
$_SESSION['contact'] = time();
Ainsi, on vérifiera toujours qu’il y ai au moins 5 minutes entre chaque envoi :
if($_SESSION['contact'] && (time()-$_SESSION['contact'] < 5*60)){ $type = 'time'; }else{ // Ici on pourra envoyer le mail }
Tester un exemple
Comme d’habitude, vous pouvez tester ce formulaire de contact directement dans mon laboratoire ou télécharger la source.







juillet 18th, 2009 on 01h21
sisi trés bon tuto merci bcp !