Как я могу отправить электронное письмо с вложениями из формы PHP? - PullRequest
5 голосов
/ 26 августа 2009

Как мне отправить электронное письмо с вложениями из формы PHP?

Ответы [ 4 ]

12 голосов
/ 26 августа 2009

Вероятно, лучше использовать существующий инструмент, как другие предложили в своих ответах. Однако, если вы хотите сделать что-то свое или просто понять, продолжайте читать.

HTML

На самом деле в вашем HTML есть только два требования для отправки файловых вложений.

  • Ваша форма должна иметь этот атрибут: enctype="multipart/form-data"
  • Вам нужно хотя бы одно поле, например <input type="file" name="examplefile">. Это позволяет пользователю найти файл для вложения.

Если у вас есть оба из них, браузер загрузит все вложенные файлы вместе с отправкой формы .

Примечание: они сохраняются как временные файлы на сервере. В этом примере мы возьмем их данные и отправим по электронной почте, но если вы переместите временные файлы в постоянное место, вы только что создали форму для загрузки файлов.

Формат электронной почты MIME

Этот учебник отлично подходит для понимания того, как создать электронную почту MIME (которая может содержать HTML-контент, текстовую версию, вложения и т. Д.) В PHP. Я использовал это как отправную точку.

Обычно вы делаете три вещи:

  • Заранее заявите, что в этом письме будет содержаться несколько типов контента
  • Объявите строку текста, которую вы будете использовать для разделения различных разделов
  • Определите каждый раздел и вставьте соответствующий контент. В случае файловых вложений вы должны указать тип и кодировать их в ASCII.
    • Каждый раздел будет иметь content-type, например image/jpg или application/pdf.. Более подробную информацию можно найти здесь . (Мой пример сценария извлекает эту информацию из каждого файла, используя встроенные функции PHP.)

PHP

После отправки формы любые файлы, загруженные браузером (см. Раздел HTML), будут доступны через переменную $_FILES, которая содержит «Ассоциативный массив элементов, загруженных в текущий скрипт через метод HTTP POST. '

Документация на $_FILES является паршивой, но после загрузки вы можете запустить print_r($_FILES), чтобы посмотреть, как она работает. Будет выведено что-то вроде этого:

Array ( [examplefile] => Array ( [name] => your_filename.txt 
[type] => text/plain [tmp_name] => 
C:\path\to\tmp\file\something.tmp [error] => 0 [size] => 200 ) ) 

Затем вы можете получить данные в соответствующем временном файле, используя file_get_contents($_FILES['examplefile']['tmp_name']).

Примечание по ограничению размера файла

php.ini имеет некоторые настройки, которые ограничивают размер вложения. См. это обсуждение для получения дополнительной информации.

Пример PHP-функции

Я создал следующую функцию, которую можно включить на странице и использовать для сбора любых вложенных файлов, отправленных с формой. Не стесняйтесь использовать его и / или адаптировать для своих нужд.

Общий лимит вложения произвольный, но большие суммы могут привести к сбою сценария mail() или могут быть отклонены отправляющим или получающим сервером электронной почты. Проведите собственное тестирование.

(Примечание. Функция mail() в PHP зависит от информации в php.ini о том, как отправлять электронную почту.)

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.';
    }
  }    
}

Если вы хотите увидеть, что здесь происходит, закомментируйте вызов на mail() и сделайте так, чтобы он выводил вывод на ваш экран.

2 голосов
/ 26 августа 2009

Для отправки настоящего электронного письма я бы порекомендовал использовать библиотеку PHPMailer , это делает все намного проще.

1 голос
/ 26 августа 2009

Возможно, вы захотите проверить SwiftMailer . В этом .

есть хорошее руководство по .
1 голос
/ 26 августа 2009

хороший учебник здесь

код

<?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";
?> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...