KioskeaKioskeaCommentCaMarcheInscrivez-vous, c'est gratuit !
Vendredi 16 mai 2008 - 13:17:08

[Langages] Envoyer un mail avec pièce jointe

Avis / Logiciels Autres avis
Vous êtes ici : Astuces Programmation Langages
[Langages] Envoyer un mail avec pièce jointe kilian samedi 21 janvier 2006 à 03:06:50 kilian
Les mails , tout comme les pages web, sont livrés avec des en-têtes (headers en anglais).
Ces en-têtes servent à donner quelques détails necessaires comme l'adresse du destinataire, celle de l'envoyeur, la date de l'envoi, le sujet du mail etc....
Elles sont organisées de cette manière:
Nom_en_tete: valeur\n\r
Nom_en_tete: valeur\n\r
[...]
Nom_en_tete: valeur\n\n\r

Corps du message...

Sachant que "\n" signifie retour à la ligne, et "\r" placement en début de ligne.

C'est en partie en trifouillant dans ces en-têtes que l'on peut envoyer un mail avec pièce jointe par le biais d'un programme.
Les en-têtes spécifient également le type du message : mail en html, mail texte etc....
Pour envoyer un mail avec pièce jointe, il faut lui donner le type multipart/mixed pour signifier qu'on trouvera plusieurs parties dans ce mail (ici, le message principal et la pièce jointe).

Pour séparer ces parties on utilise ce qu'on appele une "frontière" (boundary en anglais).
Cette frontière doit être une chaine de caractère assez unique pour ne pas être retrouvée dans votre message principal.

Prenons par exemple "didondinaditondelosdudosdodudundodudindon" (prenez des caractères acsii de préférence, je ne sais pas comment un client mail réagira avec des caractères evoluées).
Pour nos en-têtes, on se contentera de declarer l'adresse de l'envoyeur, la version de MIME et le type du message, et, comme c'est un message avec pièce jointe, il nous faut préciser la frontière:
From: expediteur@domaine.fr\r\n
MIME-Version: 1.0\r\n
Content-Type: multipart/mixed; boundary="didondinaditondelosdudosdodudundodudindon"\r\n\n

(Notez que la fin des en-têtes se caractérise par deux sauts de ligne).
Pour entamer une partie du corps du mail, on va commencer par afficher notre frontière. Lorsqu'une frontière ouvre une partie, elle est précédée de deux tirets :"--". On le terminera avec un saut de ligne:
--didondinaditondelosdudosdodudundodudindon\n

On va dire que le message lisible du mail sera un simple texte. On mets donc le type de cette partie (avec le jeu de caractère qui convient, ici le jeu de caractère qu'utilise l'alphabet français) :
Content-Type: text/plain; charset=ISO-8859-1\r\n\n

Message principal du mail.\n\n

La suite, va concerner le fichier-joint. Pour mettre des données binaires dans un mail, on utilise souvent un standard appelé base 64 qui permet de
transformer ces données en caractères.
On va donc rebalancer notre frontière pour délimiter cette partie et préciser dans nos en-têtes:
_ Le type du fichier (on va prendre un fichier doc pour word)
_ Le type d'encodage du fichier (ici base 64)
_ La disposition du fichier dans le mail (pièce jointe) et son nom.
--didondinaditondelosdudosdodudundodudindon\n
Content-Type: application/msword; name="nom_fichier"\r\n
Content-Transfer-Encoding: base64\r\n
Content-Disposition: attachment; filename="nom_fichier"\r\n\n

A la suite, nous afficherons le contenu de notre fichier encodé en base64.

Et enfin, nous allons fermer notre frontière pour de bon.
Pour fermer une frontière, il faut la faire suivre et précéder de deux tirets "--", soit:
--didondinaditondelosdudosdodudundodudindon--\n


Et vouaala. Le mail n'a plus qu'à être envoyé.
Histoire de concrétiser tout ça, on va implémenter l'envoi de ce mail en Php (pratique avec ses fonctions mail() et base64_encode() toutes prêtes):
<?php
$boundary='didondinaditondelosdudosdodudundodudindon';
//En-têtes du mail
$headers="From: expediteur@domaine.fr\r\n
MIME-Version: 1.0\r\n
Content-Type: multipart/mixed; boundary=\"$boundary\"\r\n\n";

//Corps du mail en commençant par le message principal
$body="--". $boundary ."\n
Content-Type: text/plain; charset=ISO-8859-1\r\n\n
Message principal du mail.\n\n";

/* Piece jointe, on va dire que notre fichier s'appele bidule.doc et qu'il se situe dans le repertoire courant */

$fichier=file_get_contents('./bidule.doc');
/* On utilise aussi chunk_split() qui organisera comme il faut l'encodage fait en base 64 pour se conformer aux standards */
$fichier=chunk_split( base64_encode($fichier) );

//Ecriture de la pièce jointe
$body = $body . "--" .$boundary. "\n
Content-Type: application/msword; name=\"nom_fichier\"\r\n
Content-Transfer-Encoding: base64\r\n
Content-Disposition: attachment; filename=\"nom_fichier\"\r\n\n
$fichier";

//Fermeture de la frontière
$body = $body . "--" . $boundary ."--";

//Envoi du mail
mail("destinataire@bidule.fr", "sujet", $body, $headers);
?>

Et vouala :-)

Sources et doc
_ http://www.hochfeiler.it/alvise/smtp.htm
_ http://fr2.php.net/manual/fr/function.mail.php (voir exemples dans la discussion)

 

Autres Astuces dans la catégorie Langages