La distribution d'un email se solde parfois par un échec, et par le retour d'un message contenant la nature de l'erreur.

La plupart du temps, cela signifie que l'adresse email du destinataire a été mal saisie ou que sa boîte n'existe plus. Dans le cas d'une newsletter, on peut alors supprimer cette adresse de la base de données sans pitié.

Je n'aborde pas ici la problématique de la connexion à un compte mail grâce à PHP (car le message d'erreur est bien reçu sur une boîte mail !). Je ne traiterai que du texte de l'email, afin d'en extraire l'email du destinataire "défaillant".

Voici un email typique :
Hi. This is the qmail-send program at yahoo.com. I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. : 66.196.82.7 failed after I sent the message. Remote host said: 554 delivery error: dd This user doesn't have a yahoo.fr account (mazdaxaz@yahoo.fr) [0] - mta147.mail.re1.yahoo.com --- Below this line is a copy of the message. Return-Path: Received: (qmail 10179 invoked by uid 60001); 2 Feb 2009 18:27:19 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=s1024; d=yahoo.fr; h=X-YMail-OSG:Received:X-Mailer:Date:From:Subject:To:MIME-Version:Content-Type:Message-ID; b=dyc X-YMail-OSG: t4df720VM1lynv5LrrRSPfkQ-- Received: from [90.61.194.155] by web26405.mail.ukl.yahoo.com via HTTP; Mon, 02 Feb 2009 18:27:19 GMT X-Mailer: YahooMailRC/1155.45 YahooMailWebService/0.7.260.1 Date: Mon, 2 Feb 2009 18:27:19 +0000 (GMT) From: Webmaster MaxiMoi200 Subject: Coucou To: mazdaxaz@yahoo.fr MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="0-1485629822-1233599239=:7943" Message-ID: --0-1485629822-1233599239=:7943 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Coucou=0A=0A=0A=0A --0-1485629822-1233599239=:7943 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable

Un langage un peu étrange, mais qui semble signifier que expediteur@yahoo.fr a envoyé un email à destinataire_faux@yahoo.fr et que ce destinataire n'existe pas ! On remarque que l'adresse email du destinataire est indiquée en les signes "<" et ">". Le but est de l'extraire afin de la supprimer de la base de données. Pour cela, nous allons utiliser les fonctions PHP explode, str_replace et eregi

La fonction explode permet de séparer un texte en morceaux en utilisant un séparateur. Dans notre cas, deux séparateurs paraissent tout à fait intéressants : < et >. Pour faciliter le traitement, il est préférable de n'utiliser qu'un seul séparateur. Pour cela, nous allons remplacer dans le texte toutes les occurences de > par des <. Il suffit d'utiliser la fonction PHP str_replace.
Sa syntaxe est la suivante : str_replace("chaîne à remplacer","chaîne de remplacement","texte")

Dans notre cas, si $texte est le texte du message, alors le texte avec un seul délimiteur < est obtenu ainsi :
$texte_un_seul_delimiteur = str_replace('>','<',$texte);

Afin d'isoler toutes les portions de texte entourées par deux '<' (dont l'adresse email qui nous intéresse), nous utilisons la fonction PHP explode. Cette fonction retourne un tableau contenant toutes les portions (ou segments) de texte qui étaient délimitées par le séparateur spécifié. Syntaxe : explode("séparateur","texte")

$tableau contient tous les segments de $texte_un_seul_delimiteur séparés par "<" :

$tableau = explode('<',$texte_un_seul_delimiteur);

A présent, itérons sur ce tableau afin de déterminer quels éléments ressemblent syntaxiquement à des adresses email. Pour cela, utilisons la fonction PHP eregi. Elle permet de comparer une chaîne de caractère à une expression générique, dite "régulière". Nous ne rentrerons pas dans le détail des expression régulières ici. Une expression régulière d'une adresse email ressemble à : $pattern = "^([A-Za-z0-9\.|-|_]{1,60})([@])([A-Za-z0-9\.|-|_]{1,60})(\.)([A-Za-z]{2,3})$". Certes, cela a un peu l'air barbare... Donc, si une chaîne $test répond positivement à ereg($pattern,$test), c'est qu'il s'agit dans notre cas d'une adresse email !

for($i=0;$i < count($tableau);$i++){
 if(ereg($pattern,$tableau[$i])){
  echo($tableau[$i]);
 }
}

A ce stade, quatre adresses email vont apparaître à l'écran : destinataire_faux@yahoo.fr, expediteur@yahoo.fr, expediteur@yahoo.fr, identifiant.message@web26405.mail.ukl.yahoo.com

Parmi celles ci, "deux" sont connues d'avance : expediteur@yahoo.fr. On conaît également la structure de l'identifiant message (surtout le domaine). Il suffit d'ajouter des tests :

for($i=0;$i < count($tableau);$i++){
 if(ereg($pattern,$tableau[$i]) & !ereg('mail.ukl.yahoo.com',$tableau[$i] & $tableau[$i]!='expediteur@yahoo.fr'){
  echo($tableau[$i]);
 }
}

Seul destinataire_faux@yahoo.fr passe les tests, et peut donc être récupéré pour être utilisé afin par exemple d'être supprimé d'une base de données.