6 votes

Comment puis-je envoyer un courriel avec des pièces jointes à partir d'un formulaire PHP ?

Comment puis-je envoyer un courriel avec des pièces jointes à partir d'un formulaire PHP ?

12voto

Nathan Long Points 30303

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 comme image/jpg o application/pdf. Plus d'informations sont disponibles aquí . (Mon exemple script tire ces informations de chaque fichier à l'aide de fonctions PHP intégrées).

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.

1voto

Phill Pafford Points 32046

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";
?>

1voto

Anti Veeranna Points 6319

Pour l'envoi de l'e-mail proprement dit, je recommande d'utiliser l'option Bibliothèque PHPMailer cela rend tout beaucoup plus facile.

1voto

Zed Points 27408

Vous pourriez vouloir vérifier SwiftMailer . Il a une belle tutoriel sur ce .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X