Envoyer un email en PHP

Général

Comment envoyer un mail au format HTML, tout en évitant qu'il se loge dans le courrier indésirable ?

Pour commencer, petite présentation sur l'utilisation de la fonction mail() en PHP :

1 mail($to, $subject, $content, $headers);

La variable $to : le destinataire

$to contient le ou les destinataires de l'E-Mail. Les destinataires peuvent être de la forme :

  • adresse-mail@fai.fr
  • Nom du Contact <adresse-mail@fai.fr>

Pour ajouter un autre contact, il suffit d'ajouter une virgule : adresse-mail@fai.fr, adresse-mail-2@fai2.fr

La variable $subject : le sujet

C'est l'objet de l'email.

Évitez de mettre des caractères spéciaux, au risque d'avoir un mauvais encodage.

La variable $content : le contenu

Cette variable contient le corps de l'email, votre message.

La variable $headers : les en-têtes

Cette variable sert à ajouter des en-têtes supplémentaires (From, Cc, Bcc, ...).

Les en-têtes supplémentaires doivent être séparés par \r\n.

Passage à la ligne

Un passage à la ligne dans le code source d'un email doit être : \r\n.

Cependant, la messagerie Microsoft (hotmail/live) remplace le \n automatiquement par \r\n; ce qui fait que l'on se retrouve avec \r\r\n.

Pour régler ce petit soucis :

1 if(preg_match("#@(hotmail|live|msn).[a-z]{2,4}$#", $to))
2 {
3     $passage_ligne = "\n";
4 }
5 else
6 {
7     $passage_ligne = "\r\n";
8 }

Et donc à chaque fois que l'on souhaitera faire un retour à la ligne, on utilisera cette variable.

Boundary

Un boundary (frontière) va permettre de séparer les différentes parties de notre email.

Un boundary s'ouvre comme ceci :

1 ----=Chaîne_aléatoire

Et se referme ainsi :

1 --

Pour faire la chaîne aléatoire, la méthode la plus utilisée est de faire un hachage d'un nombre aléatoire :

1 $boundary = "-----=".md5(rand());

La fonction rand() permet d'obtenir un nombre aléatoire, puis la fonction md5() permet de hacher cette chaîne.

À la fin, l'email devra être de la forme :

1 Headers
2 Ouverture boundary
3 Déclaration de type Texte
4 Texte
5 Ouverture boundary
6 Déclaration de type HTML
7 HTML
8 Fermeture boundary
9 Fermeture boundary

Afin d'éviter une fois de plus le courrier indésirable, il faut aussi fournir l'email sans aucune balise HTML, juste le texte brut.

Même si cela est déconseillé, vu que ce message en texte ne sera jamais affiché, il vous est possible de mettre totalement autre chose (ou alors, ne mettre que le sujet).

Il existe une fonction PHP qui pourrait servir dans ce cas-là : strip_tags. Celle-ci permet de retourner seulement la partie texte de votre code HTML.

Plus d'informations sur php.net.

Headers / En-têtes

Les headers de l'email sont ses en-têtes.

Voilà ce que devront être les headers de votre email :

1 $headers = "From: \"Votre Nom\"<votre-adresse-mail@votre-fai.fr>" . $passage_ligne;
2 $headers.= "Reply-to: \"Votre Nom\" <votre-adresse-mail@votre-fai.fr>" . $passage_ligne;
3 $headers.= "MIME-Version: 1.0" . $passage_ligne;
4 $headers.= "Content-Type: multipart/alternative;" . $passage_ligne . " boundary=\"" . $boundary . "\"" . $passage_ligne;
  • L'adresse email de l'expéditeur
  • L'adresse email pour la réponse à l'email (normalement la même)
  • La version de l'email
  • Le type du contenu de l'E-Mail (on choisit multipart/alternative car il y aura Texte + HTML)

Message / Content

Nous avons vu qu'il fallait créer deux textes (un au format HTML, et un au format TEXT).

Nous allons arranger notre message comme ceci :

 1 Ouverture Boundary (1)
 2 Content-Type: text/plain; charset="ISO-8859-1"
 3 Content-Transfer-Encoding: 8bit
 4 Message au format texte
 5 Ouverture Boundary (2)
 6 Content-Type: text/html; charset="ISO-8859-1"
 7 Content-Transfer-Encoding: 8bit
 8 Message au format HTML
 9 Fermeture Boundary (2)
10 Fermeture Boundary (1)

En PHP :

 1 $message = $passage_ligne . $boundary . $passage_ligne;
 2 
 3 $message .= "Content-Type: text/plain; charset=\"ISO-8859-1\"" . $passage_ligne;
 4 $message .= "Content-Transfer-Encoding: 8bit" . $passage_ligne;
 5 $message .= $passage_ligne . $message_txt . $passage_ligne;
 6 
 7 $message .= $passage_ligne . "--" . $boundary . $passage_ligne;
 8 
 9 $message .= "Content-Type: text/html; charset=\"ISO-8859-1\"" . $passage_ligne;
10 $message .= "Content-Transfer-Encoding: 8bit" . $passage_ligne;
11 $message .= $passage_ligne . $message_html . $passage_ligne;
12 
13 $message .= $passage_ligne . "--" . $boundary . "--" . $passage_ligne;
14 $message .= $passage_ligne . "--" . $boundary . "--" . $passage_ligne;

Code complet

 1 $to = 'adresse-email@fai.fr';
 2 
 3 if (preg_match("#@(hotmail|live|msn).[a-z]{2,4}$#", $to))
 4 {
 5     $passage_ligne = "\n";
 6 }
 7 else
 8 {
 9     $passage_ligne = "\r\n";
10 }
11 
12 $boundary = "-----=".md5(rand());
13 
14 $sujet = "Objet du mail";
15 $message_html = '.....';
16 $message_txt = strip_tags($message_html);
17 
18 $headers = "From: \"Nom\"<adresse@fai.fr>" . $passage_ligne;
19 $headers.= "Reply-to: \"Nom\" <adresse@fai.fr>" . $passage_ligne;
20 $headers.= "MIME-Version: 1.0" . $passage_ligne;
21 $headers.= "Content-Type: multipart/alternative;" . $passage_ligne . " boundary=\"" . $boundary . "\"" . $passage_ligne;
22 
23 $message = $passage_ligne . $boundary . $passage_ligne;
24 
25 $message .= "Content-Type: text/plain; charset=\"ISO-8859-1\"" . $passage_ligne;
26 $message .= "Content-Transfer-Encoding: 8bit" . $passage_ligne;
27 $message .= $passage_ligne . $message_txt . $passage_ligne;
28 
29 $message .= $passage_ligne . "--" . $boundary . $passage_ligne;
30 
31 $message .= "Content-Type: text/html; charset=\"ISO-8859-1\"" . $passage_ligne;
32 $message .= "Content-Transfer-Encoding: 8bit" . $passage_ligne;
33 $message .= $passage_ligne . $message_html . $passage_ligne;
34 
35 $message .= $passage_ligne . "--" . $boundary . "--" . $passage_ligne;
36 $message .= $passage_ligne . "--" . $boundary . "--" . $passage_ligne;
37 
38 if (mail($to, $sujet, $message, $headers))
39 {
40     echo 'E-Mail envoyé !';
41 }
42 else
43 {
44     echo "Impossible d'envoyer le E-Mail.";
45 }

PHP

Article publié le 30 Août 2010.

Commentaires