Fonctions PHP Envoyer un e-mail

Définitions
Définition du saut de ligne

On commence par définir le retour à la ligne en fonction de la messagerie du destinataire
Le but étant que le message s'affiche correctement chez la personne qui va lire le message.

<?php
if (!preg_match("#^[a-z0-9._-]+@(hotmail|live|msn).[a-z]{2,4}$#", $mail))
{
$passage_ligne = "\r\n"; // pour hotmail, live messager, msn
}
else
{
$passage_ligne = "\n"; // pour tous les autres
}
?>

Définition des boundary

Le boundary est utile lorsque vous souhaitez constituer un mail multi-documents ayant des content-type différents. Dans notre cas, nous allons créer cinq types de documents :

  • L'e-mail en tant que tel, multi-document ⇨ Content-Type: multipart/mixed
  • Le bloc message ⇨ Content-Type: multipart/alternative
  • Le message au format texte ⇨ Content-Type: text/plain
  • Le message au format HTML ⇨ Content-Type: text/html
  • Les pièces jointes ⇨ Content-Type: = < Type MIME de la pièce jointe >
Le boundary est une chaine de caractères générés aléatoirement, qui permet donc, de découper un e-mail.
Il faut voir les boundary comme des parenthèses dans une fonction mathémathique.
S'il est ouvert par : --86d4d6c43fe8918fa558d49173764371
il doit être fermé par : --86d4d6c43fe8918fa558d49173764371--

<?php
$boundary = md5(rand()); // Génération du boundary principale
$boundary_alt = md5(rand()); // Génération du boundary alternatif
?>

Définition des destinataires
<?php
// Correspond au A: d'un e-mail
$mail = "mondestinataire1@test.com,mondestinataire2@test.com";
?>

Définition du sujet de l'e-mail
<?php
// Correspond à l'Objet: d'un e-mail
$sujet = "blablabla";
?>

Définition de l'entête de l'e-mail
<?php
// E-mail de l'émetteur
$header = "From: noreply@test.com".$passage_ligne;
// E-mail(s) en copie
$header .= "Cc: toto@test.com,titi@test.com".$passage_ligne;
// E-mail(s) en copie cachée
$header .= "Bcc: tutu@test.com".$passage_ligne;
$header .= "MIME-Version: 1.0".$passage_ligne;
$header .= "X-Priority: 1".$passage_ligne;
// Déclaration du type MIME de l'e-mail
$header .= "Content-Type: multipart/mixed;".$passage_ligne;
// Déclaration du boundary principal
$header .= "boundary=".$boundary.$passage_ligne;
?>

Message
Ouverture du message

Le message est délimité par la boundary alternatif.
Il est composé de deux sections :

  • Le message au format HTML
  • Le message au format texte, qui se substitu au message HTML si la messagerie du destinataire n'interprête pas le message balisé.
    Ce dernier est obligatoire !

<?php
// Overture du boundary principal
$message = $passage_ligne."--".$boundary.$passage_ligne;
// Déclaration du type MIME du bloc message
$message .= "Content-Type: multipart/alternative;".$passage_ligne;
// Déclaration du boundary alternatif
$message .= "boundary=".$boundary_alt.$passage_ligne;
?>

Création du message HTML

On commence par composer notre message HTML dans une variable, ici $message_html.

<?php
$message_html = "<html>";
$message_html .= "<body style='font-size:14px;'>";
[...] // Ajouter ICI votre message en HTML
$message_html .= "</body>";
$message_html .= "<html>";
?>

TRES IMPORTANT : On coupe la message HTML, avec la fonction wordwrap() tous les 75 caractères afin de corriger un bug lié à l'interprétation des chaines trop longue.

<?php
$message_html = wordwrap($message_html, 75, "\n");
?>

Enfin, on ecrit le message html dans notre message principal.

<?php
// Ouverture du boundary alternatif
$message .= $passage_ligne."--".$boundary_alt.$passage_ligne;
// Déclaration du type MIME du message HTML
$message .= "Content-Type: text/html; charset='utf-8'".$passage_ligne;
// Déclaration de l'encogage du message HTML
$message .= "Content-Transfer-Encoding: 8bit".$passage_ligne;
// Ecriture du message HTML
$message .= $passage_ligne.$message_html.$passage_ligne;
?>

On sépare le message HTML du message texte avec le boundary alternatif.

<?php
$message .= $passage_ligne."--".$boundary_alt.$passage_ligne;
?>

Création du message texte

On ecrit le message texte dans notre message principal directement.

<?php
// Déclaration du type MIME du message HTML
$message .= "Content-Type: text/plain; charset='utf-8'".$passage_ligne;
// Déclaration de l'encogage du message HTML
$message .= "Content-Transfer-Encoding: 8bit".$passage_ligne;
// Ecriture du message HTML
$message .= $passage_ligne."Vous devez acceptez les messages html pour visualiser les informations correctement".$passage_ligne;
// Fermeture du boundary alternatif
$message .= $passage_ligne."--".$boundary_alt."--".$passage_ligne;
?>

Insertion des pièces jointes

Au préalable on charge la liste des pièces jointes (nom + extension) dans un tableau, ici $PJDS.

<?php
// On boucle autant de fois (X) que l'on a de pièces jointes dans la tableau $PJDS
for ($i=1; $i<=X;$i++)
{
if ($PJDS[$i] != "")
{
$message .= $passage_ligne."--".$boundary.$passage_ligne;
$fichier = fopen("MONREPERTOIRE/".$PJDS[$i], "r");
$attachement = fread($fichier, filesize("MONREPERTOIRE/".$PJDS[$i]));
$attachement = chunk_split(base64_encode($attachement));
fclose($fichier);
$message .= "Content-Type: ".mime_content_type("MONREPERTOIRE/".$PJDS[$i])."; name=".$PJDS[$i].$passage_ligne;
$message .= "Content-Transfer-Encoding: base64".$passage_ligne;
$message .= "Content-Disposition: attachment; filename=".$PJDS[$i].$passage_ligne;
$message .= $passage_ligne.$attachement.$passage_ligne.$passage_ligne;
}
}
?>

Fermeture du boundary principal
<?php
$message .= $passage_ligne."--".$boundary."--".$passage_ligne.$passage_ligne;
?>

Envoyer l'e-mail
<?php
$res = mail($mail,$sujet,$message,$header);
if ($res == true)
{
// e-mail envoyé avec succès !
}
else
{
// echec de l'envoi d'e-mail !
}
?>

En résumé
E-mail
Content-Type: multipart/mixed
boundary: 41e19f7f60fe265278ebd9d3f078af7c // Déclaration du boundary principal
--41e19f7f60fe265278ebd9d3f078af7c // ouverture du boundary principal
Message
Content-Type: multipart/alternative
boundary: 8c935a9e75f3cf9cbfcc331251c7a410 // Déclaration du boundary alternatif
--8c935a9e75f3cf9cbfcc331251c7a410 // ouverture du boundary alternatif
message HTML
Content-Type: text/html
--8c935a9e75f3cf9cbfcc331251c7a410 // séparation par le boundary alternatif
message texte
Content-Type: text/plain
--8c935a9e75f3cf9cbfcc331251c7a410-- // fermeture du boundary alternatif
--41e19f7f60fe265278ebd9d3f078af7c // séparation par le boundary principal
Pièce jointe 1
Content-Type: < Type MIME de la pièce jointe >
--41e19f7f60fe265278ebd9d3f078af7c // séparation par le boundary principal
Pièce jointe N
Content-Type: < Type MIME de la pièce jointe >
--41e19f7f60fe265278ebd9d3f078af7c-- // fermeture du boundary principal