Comment puis-je envoyer un courriel avec des pièces jointes à partir d'un formulaire PHP ?
Réponses
Trop de publicités?Il est probablement préférable d'utiliser un outil existant, comme d'autres l'ont suggéré dans leurs réponses. Toutefois, si vous souhaitez créer le vôtre ou simplement comprendre comment le faire, poursuivez votre lecture.
Le HTML
Il n'y a vraiment que deux exigences dans votre HTML pour envoyer des pièces jointes.
- Votre formulaire doit avoir cet attribut :
enctype="multipart/form-data"
- Vous avez besoin d'au moins un champ comme
<input type="file" name="examplefile">
. Cela permet à l'utilisateur de rechercher un fichier à joindre.
Si vous avez les deux, le navigateur téléchargera les fichiers joints en même temps que la soumission du formulaire. .
Remarque : ces fichiers sont enregistrés en tant que fichiers temporaires sur le serveur. Pour cet exemple, nous allons prendre leurs données et les envoyer par e-mail, mais si vous déplacez les fichiers temporaires vers un emplacement permanent, vous venez de créer un formulaire de téléchargement de fichiers.
Le format de courriel MIME
Ce tutoriel est excellent pour comprendre comment construire un courriel MIME (qui peut contenir du contenu HTML, une version en texte brut, des pièces jointes, etc) en PHP. Je l'ai utilisé comme point de départ.
En gros, vous faites trois choses :
- Déclarez d'emblée que ce courriel contiendra plusieurs types de contenu.
- Déclarez une chaîne de texte que vous utiliserez pour séparer les différentes sections
- Définissez chaque section et collez-y le contenu approprié. Dans le cas de pièces jointes de fichiers, vous devez préciser le type et les encoder en ASCII.
- Chaque section aura un
content-type
commeimage/jpg
oapplication/pdf.
Plus d'informations sont disponibles aquí . (Mon exemple script tire ces informations de chaque fichier à l'aide de fonctions PHP intégrées).
- Chaque section aura un
Le PHP
Une fois le formulaire soumis, tous les fichiers téléchargés par le navigateur (voir la section HTML) seront disponibles via l'interface de l'utilisateur. $_FILES
qui contient "Un tableau associatif d'éléments téléchargés dans le script actuel via la méthode HTTP POST".
El documentation en $_FILES
est minable, mais après un téléchargement, vous pouvez exécuter print_r($_FILES)
pour voir comment cela fonctionne. Vous obtiendrez quelque chose comme ceci :
Array ( [examplefile] => Array ( [name] => your_filename.txt
[type] => text/plain [tmp_name] =>
C:\path\to\tmp\file\something.tmp [error] => 0 [size] => 200 ) )
Vous pouvez ensuite récupérer les données dans le fichier temporaire associé en utilisant file_get_contents($_FILES['examplefile']['tmp_name'])
.
Note complémentaire sur les limites de taille des fichiers
php.ini
a certains paramètres qui limitent la taille des pièces jointes. Voir cette discussion pour plus d'informations.
Un exemple de fonction PHP
J'ai créé la fonction suivante, qui peut être incluse dans la page et utilisée pour rassembler tous les fichiers joints soumis avec un formulaire. N'hésitez pas à l'utiliser et/ou à l'adapter à vos besoins.
La limite du nombre total de pièces jointes est arbitraire, mais de grandes quantités risquent d'encombrer l'application. mail()
script ou être rejeté par un serveur de courrier électronique émetteur ou récepteur. Faites vos propres tests.
(Note : Le mail()
en PHP dépend des informations contenues dans php.ini
pour savoir comment envoyer votre courriel).
function sendWithAttachments($to, $subject, $htmlMessage){
$maxTotalAttachments=2097152; //Maximum of 2 MB total attachments, in bytes
$boundary_text = "anyRandomStringOfCharactersThatIsUnlikelyToAppearInEmail";
$boundary = "--".$boundary_text."\r\n";
$boundary_last = "--".$boundary_text."--\r\n";
//Build up the list of attachments,
//getting a total size and adding boundaries as needed
$emailAttachments = "";
$totalAttachmentSize = 0;
foreach ($_FILES as $file) {
//In case some file inputs are left blank - ignore them
if ($file['error'] == 0 && $file['size'] > 0){
$fileContents = file_get_contents($file['tmp_name']);
$totalAttachmentSize += $file['size']; //size in bytes
$emailAttachments .= "Content-Type: "
.$file['type'] . "; name=\"" . basename($file['name']) . "\"\r\n"
."Content-Transfer-Encoding: base64\r\n"
."Content-disposition: attachment; filename=\""
.basename($file['name']) . "\"\r\n"
."\r\n"
//Convert the file's binary info into ASCII characters
.chunk_split(base64_encode($fileContents))
.$boundary;
}
}
//Now all the attachment data is ready to insert into the email body.
//If the file was too big for PHP, it may show as having 0 size
if ($totalAttachmentSize == 0) {
echo "Message not sent. Either no file was attached, or it was bigger than PHP is configured to accept.";
}
//Now make sure it doesn't exceed this function's specified limit:
else if ($totalAttachmentSize>$maxTotalAttachments) {
echo "Message not sent. Total attachments can't exceed " . $maxTotalAttachments . " bytes.";
}
//Everything is OK - let's build up the email
else {
$headers = "From: yourserver@example.com\r\n";
$headers .= "MIME-Version: 1.0\r\n"
."Content-Type: multipart/mixed; boundary=\"$boundary_text\"" . "\r\n";
$body .="If you can see this, your email client "
."doesn't accept MIME types!\r\n"
.$boundary;
//Insert the attachment information we built up above.
//Each of those attachments ends in a regular boundary string
$body .= $emailAttachments;
$body .= "Content-Type: text/html; charset=\"iso-8859-1\"\r\n"
."Content-Transfer-Encoding: 7bit\r\n\r\n"
//Inert the HTML message body you passed into this function
.$htmlMessage . "\r\n"
//This section ends in a terminating boundary string - meaning
//"that was the last section, we're done"
.$boundary_last;
if(mail($to, $subject, $body, $headers))
{
echo "<h2>Thanks!</h2>Form submitted to " . $to . "<br />";
} else {
echo 'Error - mail not sent.';
}
}
}
Si vous voulez voir ce qu'il se passe ici, commentez l'appel à mail()
et faire en sorte qu'il renvoie la sortie sur votre écran à la place.
Joli tutoriel ici
Le code
<?php
//define the receiver of the email
$to = 'youraddress@example.com';
//define the subject of the email
$subject = 'Test email with attachment';
//create a boundary string. It must be unique
//so we use the MD5 algorithm to generate a random hash
$random_hash = md5(date('r', time()));
//define the headers we want passed. Note that they are separated with \r\n
$headers = "From: webmaster@example.com\r\nReply-To: webmaster@example.com";
//add boundary string and mime type specification
$headers .= "\r\nContent-Type: multipart/mixed; boundary=\"PHP-mixed-".$random_hash."\"";
//read the atachment file contents into a string,
//encode it with MIME base64,
//and split it into smaller chunks
$attachment = chunk_split(base64_encode(file_get_contents('attachment.zip')));
//define the body of the message.
ob_start(); //Turn on output buffering
?>
--PHP-mixed-<?php echo $random_hash; ?>
Content-Type: multipart/alternative; boundary="PHP-alt-<?php echo $random_hash; ?>"
--PHP-alt-<?php echo $random_hash; ?>
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Hello World!!!
This is simple text email message.
--PHP-alt-<?php echo $random_hash; ?>
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
<h2>Hello World!</h2>
<p>This is something with <b>HTML</b> formatting.</p>
--PHP-alt-<?php echo $random_hash; ?>--
--PHP-mixed-<?php echo $random_hash; ?>
Content-Type: application/zip; name="attachment.zip"
Content-Transfer-Encoding: base64
Content-Disposition: attachment
<?php echo $attachment; ?>
--PHP-mixed-<?php echo $random_hash; ?>--
<?php
//copy current buffer contents into $message variable and delete current output buffer
$message = ob_get_clean();
//send the email
$mail_sent = @mail( $to, $subject, $message, $headers );
//if the message is sent successfully print "Mail sent". Otherwise print "Mail failed"
echo $mail_sent ? "Mail sent" : "Mail failed";
?>
Pour l'envoi de l'e-mail proprement dit, je recommande d'utiliser l'option Bibliothèque PHPMailer cela rend tout beaucoup plus facile.
Vous pourriez vouloir vérifier SwiftMailer . Il a une belle tutoriel sur ce .