<?php

// ------------------------------------------------------------------------- //
// Contrôle e-mail : syntaxe, nom de domaine, serveur, utilisateur           //
// ------------------------------------------------------------------------- //
// Auteur: gilles <gilles@proxyline.net>                                     //
// Web:    http://ww2.galart.net/controle_email.php4                         //
// ------------------------------------------------------------------------- //

/*
Cette fonction contrôle la validité d'une adresse e-mail sur les critères suivants :
- syntaxe et orthographe orthodoxes
- existence du nom de domaine
- existence d'un serveur mail pour ce domaine
- existence de l'utilisateur dans ce domaine

Le dernier point est plutôt rare (c'est pourquoi je le poste ;-)) et mérite quelques précisions :
- la recherche de l'existence de l'utilisateur s'effectue en établissant une 'discussion' SMTP avec le serveur mail de l'adresse à valider.
- Le serveur renvoit (quand tout se passe bien, cf. ci-dessous) au final un code qui est soit celui d'une validation, soit ...autre chose.
- En pratique, l'une ou l'autre des réponses reste sujette à caution, ce sera à vous, si vous souhaitez affiner votre validation, d'interpréter les résultats retournés par la fonction.

Pourquoi les résultats ne sont pas fiables à 100% :
- en cas de succès, celui-ci peut-être dû à un paramétrage sur le serveur qui l'autorise à accepter n'importe quel nom d'utilisateur (passerelle qui redirigera sur un vrai serveur, système 'catch all'). Dans le premier cas, ça n'empêchera pas le vrai serveur de vous renvoyer un bounce si vous adressez réellement un mail à cet utilisateur ; dans le deuxième cas, moins gênant, il y a normalement un humain censé savoir exploiter cet e-mail (sinon, on peut supposer que le 'catch all' n'aurait pas été mis en place).
- en cas d'échec, hormis le cas réel d'inexistence, celui-là peut être dû à une indisponibilité du serveur qui empêchera donc de recevoir la validation attendue.

Dans tous les cas, la fonction vous retourne les réponses du serveur. A vous de les exploiter.

Si vous souhaitez en savoir un peu plus sur le fonctionnement SMTP et sa mise en place chez les providers, utilisez le lien sur la démo, vous obtiendrez les résultats commentés. Puis, retirez les echo, compteurs de temps, et autres commentaires avant de passer en production.
*/

/*
Par Gilles Caradec (proxyline.net) le 11/08/2002
Copyright 2002 proxyline
Libre d'utilisation, merci de conserver le copyright.
Résultats non garantis, à utiliser sous votre propre responsabilité.
*/

function controle_email ( $email )
{
        global
$return;
        global
$SERVER_NAME;
        
// nom de domaine du site exécutant ce script et qui sera utilisé pour
        // interroger le(s) serveur(s) de mail
        
$domaine = explode(".", $SERVER_NAME);
        
$nbre = count($domaine);
        
$domaine_sender = $domaine[$nbre-2].".".$domaine[$nbre-1];
        list (
$user, $domain )  = split ( "@", $email, 2 );
        
// on teste d'abord la syntaxe de l'adresse
        
echo "Voici les données retournées par la fonction controle_email :<br><br>";
        if (
eregi("^[_\.0-9a-z\-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3}$",$email))
        {
                if (
getmxrr ( $domain, $mxhosts, $weight ) )
                {
                        
$nbremx = count($mxhosts);
                        echo
"Voici le tableau \$weight (Il donne l'importance relative des serveurs de mails lorsqu'il y en a plusieurs. La valeur la plus faible représente l'importance la plus grande !):<br>";
                        while (list(
$cle, $val) = each ($weight))
                                {
                                echo
"L'index $cle du tableau correspond à la valeur $val <br>";
                                }
                        
asort ($weight);
                        echo
"<br>Voici le tableau \$weight trié par la fonction asort(\$weight)  :<br>";
                        while (list(
$cle, $val) = each ($weight))
                                {
                                echo
"L'index $cle du tableau correspond à la valeur $val <br>";
                                }
                        
reset ($weight);
                        
$cle = key($weight);
                        
$poids = current($weight);
                        echo
"<br>La plus faible valeur est $poids avec comme index : $cle<br>";
                        echo
"Nous contacterons donc d'abord le serveur \$mxhosts = $mxhosts[$cle] avec l'index \$cle = $cle, puis - s'il ne répond pas et s'il y a d'autres serveurs référencés - les autres serveurs triés par ordre d'importance décroissant.<br>";
                        echo
"<br>Voici le tableau \$mxhosts :<br>";
                        while (list(
$cle, $val) = each ($mxhosts))
                                {
                                echo
"L'index $cle du tableau correspond à la valeur $val <br>";
                                }
                        
// $iter nous servira à compter le nombre de serveurs testés
                        // avant d'obtenir une réponse SMTP positive
                        
$iter = 0;
                        
// on lance le chronomètre
                        
$top0 = top_chrono();
                        
// on se cale sur $weight trié pour faire un tour dans
                        // le bon sens des serveurs mx
                        
while (list($i, $val) = each ($weight))
                        {
                                
$top10 = top_chrono();
                                
$fp = fsockopen ( $mxhosts[$i], 25 );
                                echo
"<br>index de \$weight : $i - tentative de connexion au serveur de mail \"$mxhosts[$i]\" <br>";
                                if (
$fp )
                                {
                                echo
"<font color='#008000'>connexion réussie à \"$mxhosts[$i]\" <br></font>";
                                        
$s = 0;
                                        
$out = "";
                                        
$top1 = top_chrono();
                                        
$out = fgets ( $fp, 512 );
                                        if (
ereg ( "^220", $out ) )
                                        {
                                                echo
"<font color='#008000'>réponse de \"$mxhosts[$i]\" : \"$out\"  <br> </font>";
                                                
$top2 = top_chrono();
                                                
$temps= $top2-$top1;
                                                
$temps = number_format($temps,3,"."," ");
                                                echo
"temps de la boucle de connexion :  $temps seconde(s)<br>";
                                                
// on a obtenu une réponse du serveur, on tente de
                                                // discuter avec lui en SMTP
                                                
fputs ( $fp, "HELO $SERVER_NAME\r\n" );
                                                
$output = fgets ( $fp, 512 );
                                                echo
"<ul>";
                                                echo
"<li>réponse de \"$mxhosts[$i]\" à \"HELO $SERVER_NAME\" : $output </li>";
                                                
fputs ( $fp, "MAIL FROM: <info@".$domaine_sender.">\r\n" );
                                                
$output = fgets ( $fp, 512 );
                                                echo
"<li>réponse de \"$mxhosts[$i]\" à \"MAIL FROM: &lt;info@" . $domaine_sender . "&gt; \" : $output </li>";
                                                
fputs ( $fp, "RCPT TO: <$email>\r\n" );                         
                                                
$output = fgets ( $fp, 512 );
                                                if (
ereg ( "^250", $output ) )
                                                {
                                                        
// le serveur nous répond et connait notre destinataire
                                                        
$return[0] = true;
                                                        
$return[1] = $output;
                                                        
$return[2] = true;
                                                        
$return[3] = $mxhosts[$i];
                                                        echo
"<font color='#008000'><li>réponse de \"$mxhosts[$i]\" à \"RCPT TO: &lt;$email&gt;\"  : $output ( = 250) </li></font>";
                                                }
                                                else
                                                {
                                                        
// le serveur nous répond mais ne connait pas
                                                        // notre destinataire
                                                        
$return[0] = false;
                                                        
$return[1] .= $mxhosts[$i]." a répondu ".$output." <br>";
                                                        
$return[2] = true;
                                                        
$return[3] .= $mxhosts[$i];
                                                        echo
"<font color='#FF0000'><li>réponse de \"$mxhosts[$i]\" à \"RCPT TO: &lt;$email&gt;\"  : $output ( != 250) </li></font>";
                                                }
                                                
fputs ( $fp, "QUIT\r\n" );
                                                
fgets ($fp,512);
                                                
fclose( $fp );
                                                echo
"</ul>";
                                                if (
$return[0] == true )
                                                { break; }
                                        }
                                        else
                                        {
                                                
// serveur indifférent à notre requête
                                                
echo "\"$mxhosts[$i]\" n'a pas répondu par un code 220<br>";
                                                
$return[5] .= "\"$mxhosts[$i]\" n'a pas répondu par un code 220<br>";
                                        }
                                }
                                else
                                {
                                        
// on n'a même pas pu obtenir de connexion avec ce serveur !
                                        
echo "échec de l'établissement d'un socket avec \"$mxhosts[$i]\" <br>";
                                        
$return[5] .= "échec de l'établissement d'un socket avec \"$mxhosts[$i]\" <br>";
                                }
                                
$top11 = top_chrono();
                                
$temps= $top11-$top10;
                                
$temps = number_format($temps,3,"."," ");
                                echo
"temps de la boucle de connexion sur $mxhosts[$i] :  $temps seconde(s)<br>";
                                
$iter++;
                        }
// fin de la boucle sur le tableau des serveurs
                        
if ($iter > $nbremx)
                        {
                                
// tous les serveurs recencés ont été scannés et auncun n'a
                                // accepté une connexion ou répondu positivement
                                
$return[5] .= "Aucun serveur de mail n'a répondu positivement.<br>";
                        }
                        
// pour info, on enregistre le temps de parcours total de
                        // tous les serveurs
                        
$top3 = top_chrono();
                        
$temps= $top3-$top0;
                        
$temps = number_format($temps,3,"."," ");
                        echo
"temps global de la recherche :  $temps seconde(s)<br>";
                }
                else
                {
                        
// aucun enregistrement MX trouvé pour ce domaine
                        
if ( checkdnsrr ( $domain, "SOA" ) )
                        {
                                
$return[9] = "<br>Ce nom de domaine \"$domain\" dispose bien d'une machine, mais n'a pas de serveur mail.<br>";
                        }
                        else
                        {
                                
$return[9] = "<br>Ce nom de domaine \"$domain\" n'existe pas. Vérifiez votre orthographe.<br>";
                        }
                }
        }
        else
        {
                
$return[9] = "<br>La syntaxe et/ou l'orthographe de cette adresse \"$email\" n'est pas correcte.<br>";
        }
}

function
top_chrono()
{
$chrono= microtime();
$chrono= explode(" ",$chrono);
$chrono= $chrono[1] + $chrono[0];
return (
$chrono);
}
?>