[Plan du site]
Vous êtes ici ---
> Le Site du Zéro
> Les tutoriels
> Non-Officiels
> Site Web
> PHP
> Langage, bibliothèques et fonctions
> Lecture du tutoriel
[mail] Envoyer un mail en php
Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
Comment envoyer un mail en PHP ?
Vous me direz : rien de plus simple : j'utilise la fonction
mail() et je lui donne le destinataire, le sujet, le contenu du mail.
Alors oui, ça peut fonctionner, mais le gros problème est que, quand on utilise cette méthode, le mail a 95 % de chances de partir dans les courriers indésirables... Ce qui n'est pas vraiment très bon pour l'expéditeur.
C'est pourquoi ce tutoriel va non seulement vous apprendre à envoyer un mail qui arrivera à son destinataire, mais aussi à envoyer un e-mail en HTML. Eh oui, comme les annonces de pubs que vous recevez ou encore comme les mails du SdZ (e-mails d'avertissement de messages privés ou la
Newsletter).
05/03/2008 : Ajout de l'annexe sur les fichiers joints (Merci à Vizigr0u pour ces conseils).
Définition
L'en-tête d'un e-mail, aussi appelé
header, est la partie qui se trouve au début d'un e-mail. Elle est
invisible pour l'utilisateur lambda qui ne fait que lire ses messages.
Dans ce tutoriel, j'utiliserai le mot anglais header quand je parlerai de l'en-tête car comme vous le savez certainement, le langage informatique utilise pour ainsi dire toujours la langue anglaise ; il sera donc plus facile d'utiliser ce terme dans le cours car il sera réutilisé dans le code.
Donc le
header contient toutes les informations de l'e-mail. En voici quelques exemples :
- l'heure d'envoi,
- l'adresse mail de l'expéditeur,
- l'adresse de réponse,
- le nom du serveur qui a envoyé l'e-mail,
- par où a transité l'e-mail chez votre FAI,
- etc.
Eh, mais tu viens de nous dire que le header, nous, on ne le voyait pas ! Mais moi, je sais très bien à quelle heure mon e-mail a été envoyé et qui me l'a envoyé !
Alors certes, l'utilisateur lambda voit certaines de ces informations, mais c'est uniquement parce que votre logiciel de messagerie va
lire le
header pour ensuite vous le
traduire de manière propre.
Schéma
Quand vous créez le
header pour envoyer un e-mail avec la fonction
mail() de PHP, vous avez besoin de spécifier 4 arguments :
- l'adresse de l'expéditeur,
- l'adresse de retour,
- la version de MIME,
- le content-type du message.
Bon : maintenant, éclaircissons un peu cette liste. Les deux premiers arguments n'ont pas besoin d'explication (ou bien alors vous êtes en dessous de zéro

).
Pour ce qui est de la version du
MIME, il s'agit de dire au serveur qui va recevoir l'e-mail, quelle est la version de l'e-mail. En gros, ça permet de lui dire comment le lire.
Pour le
content-type, vous l'avez peut-être déjà rencontré. Il va servir dans le cas présent à définir ce que va contenir votre e-mail. Sachez qu'il peut aussi être utilisé en HTML pour définir le contenu d'une page, ou encore en PHP lors de la génération d'une image avec une bibliothèque graphique (pour signaler à votre navigateur de quelle façon il va devoir interpréter ce qui se trouve dans la page). On verra que le
content-type va devoir aussi être réutilisé plus tard dans le corps du message.
Alors, pour récapituler, on a maintenant le schéma d'un
header qui ressemble à cela :
- Expéditeur
- Adresse de retour
- MIME
- Content-type
Comment bien déclarer son header ?
Nous allons garder le même schéma que précédemment. Je vous le rappelle :
- Expéditeur
- Adresse de retour
- MIME
- Content-type
Je vais commencer à écrire du code, à partir de maintenant. Comme je suis en train de traiter le header, je vais mettre tout ce qui le concerne dans une variable $header.
Déclaration de l'expéditeur
Code : PHP1
2
3 | <?php
$header = "From: \"EXPEDITEUR\"<ADRESSE_EXPEDITEUR>\n";
?>
|
Déclaration de l'adresse de retour
Code : PHP1
2
3 | <?php
$header.= "Reply-to: \"RETOUR\" <ADRESSE_RETOUR>\n";
?>
|
Déclaration de la version de MIME
Code : PHP1
2
3 | <?php
$header.= "MIME-Version: 1.0\n";
?>
|
Déclaration du content-type
Code : PHP1
2
3 | <?php
$header.= "Content-Type: multipart/alternative; boundary=\"$boundary\"";
?>
|
Quelques explications
Tout d'abord, la valeur de
content-type :
multipart/alternative.
J'ai choisi d'utiliser celui-ci car mon tutoriel a pour but d'envoyer un e-mail en mode texte
et en mode HTML (je détaillerai ces modes un peu plus tard).
Il y a aussi la valeur
boundary à laquelle j'ai affecté
$boundary : je suis obligé de déclarer cette valeur ici mais je vous expliquerai plus tard le contenu de la variable et son utilité.
Un exemple concret :
Code : PHP1
2
3
4
5
6
7
8 | <?php
//=====Création du header de l'e-mail
$header = "From: \"WeaponsB\"<weaponsb@mail.fr>\n";
$header .= "Reply-to: \"WeaponsB\" <weaponsb@mail.fr>\n";
$header .= "MIME-Version: 1.0\n";
$header .= "Content-Type: multipart/alternative; boundary=\"$boundary\"";
//==========
?>
|
1er bilan
Dans cette première partie, nous avons donc appris de quoi était constitué le
header d'un e-mail et comment en créer un à notre convenance. Dans la prochaine partie, nous verrons les différents types d'e-mail et aussi le code à utiliser pour les déclarer.
Définition
Alors j'imagine que vous avez tous reçu des e-mails au moins une fois dans votre vie

, vous avez donc eu la possibilité de constater que certains ont de belles images et une belle mise en forme. Par exemple :
Au format html
Au format texte
Comme nous allons envoyer un e-mail en mode texte et en mode HTML, il va nous falloir deux variables : la première contenant le contenu de l'e-mail en mode texte que l'on appellera $message_txt, et la seconde, qui contiendra l'e-mail au format HTML, au nom de $message_html. Mais attention : ces messages devront OBLIGATOIREMENT finir par un \n.
Comment faire une déclaration de type ?
Pour effectuer une déclaration de type, il faut utiliser deux choses :
- Content-Type : XXX/XXX; charset=XXXXXX
- Content-Transfer-Encoding : XXXXXXXXXX
Si l'on veut traduire cette partie en code PHP, on obtiendra quelque chose comme cela :
Code : PHP1
2
3
4
5
6 | <?php
$message = "...";
$message .= "Content-Type: XXX/XXX; charset=\"XXXXXX\"\n";
$message .= "Content-Transfer-Encoding: XXXXXXXXXX\n\n";
$message .= "...";
?>
|
Pour information, ici j'utilise une nouvelle variable $message. Cette variable sera envoyée à la fonction mail() et contiendra l'intégralité du contenu de l'e-mail (texte et code HTML).
Vous aurez aussi remarqué que j'ai ajouté "..." avant et après ma déclaration de type. C'est parce que normalement il y a autre chose avant et après la déclaration. Je l'aborderai plus tard dans le tutoriel.
Quelques explications
Tout d'abord le
content-type (eh oui encore lui, mais je vous avais dit qu'il reviendrait

).
Ici, il va servir à dire si l'on veut mettre à la suite du texte ou du code HTML.
- Mode Texte => text/plain
- Mode HTML => text/html
Passons au
charset. Il va servir à définir le type d'encodage des caractères qui vont suivre.
J'ai utilisé ici le
charset iso-8859-1 car il est supporté par tous les webmails? contrairement à l'
UTF-8.
L'
UTF-8 peut être utilisé pour l'envoi d'un e-mail multilingue (chinois, arabe ...).
Maintenant, le dernier point : le
Content-Transfer-Encoding. Ce paramètre permet de définir sur combien de bits sera encodé le message, ce qui détermine en fait le nombre de caractères différents possibles.
Petit exemple : un e-mail avec un
Content-Transfer-Encoding réglé sur 7 bits ne pourra comprendre que 128 caractères différents.
Citation : Cours de mathsNombre de caractères = 2n (bits)
Donc un message sur 7 bits donnera : 27 = 128
et un message sur 8 bits : 28 = 256
etc ...
Donc, maintenant ça va dépendre de ce que vous mettez dans votre e-mail. Si vous voulez utiliser des accents, vous devrez obligatoirement mettre le
Content-Transfer-Encoding sur 8 bits.
Ainsi, si nous appliquons ce qui se trouve au-dessus, on devrait se retrouver pour une déclaration de mode HTML avec ceci :
Code : PHP1
2
3
4
5
6 | <?php
$message = "...";
$message .= "Content-Type: text/html; charset=\"ISO-8859-1\"\n";
$message .= "Content-Transfer-Encoding: 8bit\n\n";
$message .= "...";
?>
|
2ème bilan
Eh bien nous y voilà !
Maintenant, nous savons comment définir ce que nous allons mettre dans notre e-mail. On avance sur le chemin de la quête de l'e-mail qui ne part pas à la corbeille.

Il ne nous reste plus qu'à voir comment faire la jonction entre les différentes parties.
À vos marques, prêts ? Assemb...
STOP !!!
Eh non, ce n'est pas encore pour tout de suite.

Non, ne me regardez pas avec ces yeux-là ! Oui, ceux-là :

Ça va bientôt venir, mais il faut que je vous explique une dernière chose avant de pouvoir vous lancer.
Boundary
Je vais enfin vous expliquer ce que contient la fameuse variable
$boundary.
Déjà, pour vous donner une idée,
boundary se traduit en français par
frontière.
Boundary va donc nous permettre de séparer les différentes parties de notre e-mail, et c'est
OBLIGATOIRE. On pourrait les considérer comme des super-balises.
Le format d'une
boundary est le suivant :
Citation : Format----=Chaîne_aléatoire
Pour générer cette chaîne, nous allons utiliser deux fonctions PHP. Tout d'abord la fonction
rand() qui permet d'obtenir un nombre aléatoire, puis la fonction
md5() qui permet de hacher une chaîne (ici, nous hacherons ce que la fonction
rand() nous sortira).
Alors, si vous avez bien compris ce que je vous ai expliqué, vous devriez avoir écrit un code comme celui-ci :
Code : PHP1
2
3 | <?php
$boundary = "-----=".md5(rand());
?>
|
Et voilà ! Notre
boundary est créée.
Une
boundary étant une frontière, il lui faut bien aussi une fin. Malheureusement, la création de la
boundary comme cela ne pourra pas suffire pour le corps du message.
Il va falloir ajouter ces caractères devant à chaque fois que vous les utilisez en dehors de la déclaration qui se situe dans le
header.
Citation : caractères--
Il va aussi falloir fermer la
boundary.
Pour fermer, il suffit de la réutiliser en ajoutant à la fin.
Citation : Fin de boundary--
Et voilà qui termine cette partie sur les
boundary.
Schéma final du message
Voilà ! Alors maintenant, je vais vous dire comment faire l'assemblage avec cette dernière info.
Citation : SchémaOuverture boundary.
Déclaration de type (exemple texte).
Texte.
Ouverture boundary.
Déclaration de type (exemple HTML).
HTML.
Fermeture boundary.
Fermeture boundary.
Et voilà ! Je pense que je n'ai plus grand-chose à vous apprendre sur ce sujet. Je vous mets juste un dernier exemple de code complet pour que vous puissiez l'analyser.
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 | <?php
//=====Déclaration des messages au format texte et au format HTML
$message_txt = "Salut à tous, voici un e-mail envoyé par un script PHP.";
$message_html = "<html><head></head><body><b>Salut à tous</b>, voici un e-mail envoyé par un <i>script PHP</i>.</body></html>";
//==========
//=====Création de la boundary
$boundary = "-----=".md5(rand());
//==========
//=====Définition du sujet
$sujet = "Hey mon ami !";
//=========
//=====Création du header de l'e-mail
$header = "From: \"WeaponsB\"<weaponsb@mail.fr>\n";
$header.= "Reply-to: \"WeaponsB\" <weaponsb@mail.fr>\n";
$header.= "MIME-Version: 1.0\n";
$header.= "Content-Type: multipart/alternative;\n boundary=\"$boundary\"\n";
//==========
//=====Création du message
$message = "\n--".$boundary."\n";
//=====Ajout du message au format texte
$message.="Content-Type: text/plain;\n charset=\"ISO-8859-1\"\n";
$message.="Content-Transfer-Encoding: 8bit\n";
$message.= $message_txt."\n";
//==========
$message.= "\n--".$boundary."\n";
//=====Ajout du message au format HTML
$message.="Content-Type: text/html; charset=\"ISO-8859-1\"\n";
$message.="Content-Transfer-Encoding: 8bit\n";
$message.= $message_html."\n";
//==========
$message.= "\n--".$boundary."--\n";
$message.= "\n--".$boundary."--\n";
//==========
//=====Envoi de l'e-mail
mail("weaponsb@mail.fr",$sujet,$message,$header);
//==========
?>
|
Voyons maintenant comment joindre un fichier dans un e-mail.
Changement de l'en-tête
Bon, comme je vous l'ai déjà expliqué dans les précédentes parties, quand on veut envoyer un e-mail en texte et en HTML, on doit déclarer dans le
header le
Content-Type :
multipart/alternative.
Donc ça, c'était pour du texte et du HTML. Pour pouvoir joindre un fichier, ça va changer un petit peu.

En effet, le
Content-Type :
multipart/alternative prévient le client qu'il va recevoir du texte et du HTML, mais pas un ou plusieurs fichiers. Pour cela, on va utiliser le
Content-Type :
multipart/mixed qui lui, prévient juste le client qu'il va recevoir plusieurs parties différentes.
Donc maintenant, après les modifications, votre
header devra ressembler à cela :
Code : PHP1
2
3
4
5
6
7
8 | <?php
//=====Création du header de l'e-mail
$header = "From: \"WeaponsB\"<weaponsb@mail.fr>\n";
$header .= "Reply-to: \"WeaponsB\" <weaponsb@mail.fr>\n";
$header .= "MIME-Version: 1.0\n";
$header .= "Content-Type: multipart/mixed;\n boundary="$boundary"\n";
//==========
?>
|
Maintenant, avant d'aller plus loin, il va vous falloir comprendre ce qu'est réellement un fichier.
Citation : Définition d'un fichierUn fichier est en fait une suite de caractères. Ces caractères sont par la suite interprétés par le logiciel que vous utilisez pour l'ouvrir.
Je pense que maintenant vous aurez compris comment nous allons procéder pour joindre un fichier à un e-mail.
Il va donc nous falloir lire le contenu du fichier pour, par la suite, l'ajouter dans l'e-mail.
Comme mon tutoriel ne porte pas sur la gestion de fichier en PHP, je vais juste vous donner le code que j'utilise pour lire les fichiers joints à mes e-mails.
Code : PHP1
2
3
4
5 | <?php
$fichier = fopen("image.jpg", "r"); //on ouvre le fichier en lecture seule
$attachement = fread($fichier, filesize("image.jpg")); //on lit l'ensemble du fichier avec la fonction fread
fclose($fichier); //on ferme le fichier
?>
|
Bon : maintenant que nous avons le contenu de notre fichier, nous allons devoir l'encoder en 64 bits.
Whaouu !! Encoder ? C'est quoi, ça ? Moi je n'y connais rien en codage !
Pas de problème. Encoder, c'est remplacer un caractère ou une suite de caractères par un ou une autre.
Comment encoder un fichier en 64 bits ? Grâce au PHP, rien de plus simple ! En effet, il existe une fonction qui fait ça tout seul. C'est pas beau, ça ?
Il s'agit de la fonction
base64_encode(), que l'on va utiliser comme ceci :
Code : PHP1
2
3 | <?php
$attachement = chunk_split(base64_encode($attachement));
?>
|
Au passage, vous remarquerez que j'ai également utilisé la fonction
chunk_split() qui sert, quand elle n'a pas de second argument, à effectuer un retour à la ligne tout les 76 caractères, ce qui permet de respecter la norme
RFC 2045.
Voilà. Maintenant que nous avons notre fichier dans une variable et qu'il est au bon format, on va pouvoir l'ajouter à notre e-mail.
Pour l'ajouter, on va faire comme on avait fait quand on voulait déclarer soit du texte soit du HTML.
La déclaration se voit quand même quelque peu enrichie. On va devoir maintenant déclarer :
- le nom du fichier
- Content-Disposition: XXXXXX; filename="Nom_du_fichier"
Le
Content-Disposition permet de dire que ce qui suit devra être en fichier joint. Pour cela, on lui donnera la valeur
attachment.
Ce qui, en code, nous donnera :
Code : PHP1
2
3 | <?php
$message.= "Content-Disposition: attachment;\n filename=\"nom_fichier\"\n";
?>
|
Le
Content-Type va lui aussi changer. En effet, rappelez-vous, c'est lui qui détermine à quoi correspondent les caractères entre les deux
boundary. Le problème dans le cas présent, c'est que le
Content-Type dépendra du fichier que vous voulez joindre.

Il faudra donc le faire varier en fonction de l'extension du fichier que vous envoyez. Ces types sont définis par l'
IANA. Vous trouverez
ici une liste non exhaustive des différents types disponibles, avec descriptions.
Comme dans cet exemple nous allons joindre le fichier
image.jpg, nous allons utiliser le
Content-Type: image/jpeg. Lors de la déclaration d'un
Content-Type qui sert à joindre un fichier, on doit aussi déclarer le nom du fichier joint. Au final, nous obtiendrons une déclaration du
Content-Type similaire à celle-ci :
Code : PHP1
2
3 | <?php
$message.= "Content-Type: image/jpeg;\n name=\"nom_fichier\"\n";
?>
|
Voilà : maintenant que nous avons vu les différentes étapes, je vous mets la déclaration que vous devriez avoir obtenue si vous m'avez bien suivi.
Code : PHP1
2
3
4
5 | <?php
$message.= "Content-Type: image/jpeg;\n name=\"image.jpg\"\n";
$message.= "Content-Transfer-Encoding: base64\n";
$message.= "Content-Disposition: attachment;\n filename=\"image.jpg\"\n";
?>
|
Bon : maintenant, vous pensez que l'on va pouvoir directement balancer le fichier joint ? Eh bien non.

Évidemment, ça aurait été trop simple. Car si jamais vous essayez de mettre directement votre fichier joint dans l'e-mail, la personne qui va le recevoir aura un e-mail avec ce schéma :
- e-mail en texte
- e-mail en HTML
- pièce jointe.
Ce problème est dû au changement du
Content-Type : multipart/mixed. Pour résoudre ce problème, on va devoir déclarer à nouveau un
Content-Type : et une autre
boundary. Pour vous expliquer le mieux possible, je vais vous faire une comparaison entre le schéma actuel et le schéma final.
Citation : Schéma actuelOuverture boundary.
Déclaration de type (exemple texte).
Texte.
Ouverture boundary.
Déclaration de type (exemple HTML).
HTML.
Fermeture boundary.
Fermeture boundary.
Citation : Schéma finalOuverture boundary.
Déclaration du nouveau content-type et de la seconde boundary.
Ouverture boundary_2.
Déclaration de type (exemple texte).
Texte.
Ouverture boundary_2.
Déclaration de type (exemple HTML).
HTML.
Fermeture boundary_2.
Ouverture boundary.
Déclaration de la pièce jointe.
Fermeture boundary.
Fermeture boundary.
Voilà pour finir le code final.
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 | <?php
//=====Déclaration des messages au format texte et au format HTML
$message_txt = "Salut à tous, voici un e-mail envoyé par un script PHP.";
$message_html = "<html><head></head><body><b>Salut à tous</b>, voici un e-mail envoyé par un <i>script PHP</i>.</body></html>";
//==========
//=====Lecture et mise en forme de la pièce jointe
$fichier = fopen("image.jpg", "r");
$attachement = fread($fichier, filesize("image.jpg"));
$attachement = chunk_split(base64_encode($attachement));
fclose($fichier);
//==========
//=====Création de la boundary
$boundary = "-----=".md5(rand());
$boundary_alt = "-----=".md5(rand());
//==========
//=====Définition du sujet
$sujet = "Hey mon ami !";
//=========
//=====Création du header de l'e-mail
$header = "From: \"WeaponsB\"<weaponsb@mail.fr>\n";
$header.= "Reply-to: \"WeaponsB\" <weaponsb@mail.fr>\n";
$header.= "MIME-Version: 1.0\n";
$header.= "Content-Type: multipart/mixed;\n boundary=\"$boundary\"\n";
//==========
//=====Création du message
$message = "\n--".$boundary."\n";
$message.= "Content-Type: multipart/alternative;\n boundary=\"$boundary_alt\"\n";
$message.= "\n--".$boundary_alt."\n";
//=====Ajout du message au format texte
$message.="Content-Type: text/plain; charset=\"ISO-8859-1\"\n";
$message.="Content-Transfer-Encoding: 8bit\n";
$message.= $message_txt."\n";
//==========
$message.= "\n--".$boundary_alt."\n";
//=====Ajout du message au format HTML
$message.="Content-Type: text/html; charset=\"ISO-8859-1\"\n";
$message.="Content-Transfer-Encoding: 8bit\n";
$message.= $message_html."\n";
//==========
//=====On ferme la boundary alternative
$message.= "\n--".$boundary_alt."--\n";
//==========
$message.= "\n--".$boundary."\n";
//=====Ajout de la pièce jointe
$message.= "Content-Type: image/jpeg;\n name=\"image.jpg\"\n";
$message.= "Content-Transfer-Encoding: base64\n";
$message.= "Content-Disposition: attachment;\n filename=\"image.jpg\"\n";
$message.= "\n".$attachement."\n\n";
$message.= "\n--".$boundary."--\n";
//==========
//=====Envoi de l'e-mail
mail("weaponsb@mail.fr",$sujet,$message,$header);
//==========
?>
|
Ce tutoriel est enfin terminé.
Je pense avoir réussi à vous apprendre comment envoyer correctement un e-mail en PHP. Certaines personnes me feront peut-être remarquer que je n'ai pas tout traité ! En effet, mais s'il y a des choses que je n'ai pas abordées c'est tout simplement parce que je ne les maîtrise pas encore totalement (l'inclusion d'une image à l'intérieur d'un e-mail, par exemple). Je préfère donc ne pas en parler du tout, plutôt que de me risquer à écrire n'importe quoi.