Отправка нескольких вложений по электронной почте с помощью PHP

У меня проблема с отправкой электронной почты с несколькими вложениями. Вот код:

<?php if(isset($_POST['sendEmail'])) { foreach($_FILES['uploadEmail']['error'] as $key=>$value){ if(!$_FILES['uploadEmail']['error'][$key]){ $target_path = ""; $target_path = $target_path . basename( $_FILES['uploadEmail']['name'][$key]); if(move_uploaded_file($_FILES['uploadEmail']['tmp_name'][$key], $target_path)){ $files[] = $_FILES['uploadEmail']['name'][$key]; } } } $toEmails = explode(",",$_POST['toEmail']); $count = count($toEmails); $i = 0; $j = 1; $k = 100; $bcc = ''; while($i<$count){ $bcc .= $toEmails[$i].","; if($j==$k || $i==$count-1){ $j=1; //echo $bcc.'<br />'.$sub.'<br />'.$message.'<br /><br />'; $from = 'test@gmail.com'; $sub = $_POST['subject']; $message = $_POST['message']; ///////////////////////// $headers = 'From:'. $from . "\r\n"; $headers .= "Bcc:". $bcc . "\r\n"; // boundary $semi_rand = md5(time()); $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x"; // headers for attachment $headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"{$mime_boundary}\""; // multipart boundary $message = "This is a multi-part message in MIME format.\n\n" . "--{$mime_boundary}\n" . "Content-Type: text/html; charset=\"iso-8859-1\"\n" . "Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n"; $message .= "--{$mime_boundary}\n"; // preparing attachments for($x=0;$x<count($files);$x++){ $file = fopen($files[$x],"rb"); //echo "<br>".filesize($files[$x]); $data = fread($file,filesize($files[$x])); fclose($file); $data = chunk_split(base64_encode($data)); $message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$files[$x]\"\n" . "Content-Disposition: attachment;\n" . " filename=\"$files[$x]\"\n" . "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n"; $message .= "--{$mime_boundary}\n"; } // send ///////////////////////// mail('',$sub,$message,$headers); $bcc = ''; }else{ $j++; } $i++; } } ?> <html> <head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script> <script src="http://js.nicedit.com/nicEdit-latest.js" type="text/javascript"></script> <script type="text/javascript">bkLib.onDomLoaded(function() { new nicEditor().panelInstance('message'); // new nicEditor({fullPanel : true}).panelInstance('area2'); });</script> </head> <body> <form method="POST" enctype="multipart/form-data"> <table> <tr><td><label for="toEmail">Send To : </label></td><td><textarea id="toEmail" name="toEmail" cols="100" rows="10"></textarea></td></tr> <tr><td><label for="subject">Subject : </label></td><td><input type="text" name="subject" id="subject" size="98"></td></tr> <tr><td><label for="toEmail">Message : </label></td><td><textarea id="message" name="message" cols="100" rows="10"></textarea></td></tr> <tr><td><label for="upload[]">Attachments:</label></td><td></td></tr> <tr><td><label>1</label></td><td><input type="file" name="uploadEmail[]"></td></tr> <tr><td><label>2</label></td><td><input type="file" name="uploadEmail[]"></td></tr> <tr><td><label>3</label></td><td><input type="file" name="uploadEmail[]"></td></tr> <tr><td><label>4</label></td><td><input type="file" name="uploadEmail[]"></td></tr> <tr><td><label>5</label></td><td><input type="file" name="uploadEmail[]"></td></tr> <tr><td><label>6</label></td><td><input type="file" name="uploadEmail[]"></td></tr> <tr><td><label>7</label></td><td><input type="file" name="uploadEmail[]"></td></tr> <tr><td><label>8</label></td><td><input type="file" name="uploadEmail[]"></td></tr> <tr><td><label>9</label></td><td><input type="file" name="uploadEmail[]"></td></tr> <tr><td><label>10</label></td><td><input type="file" name="uploadEmail[]"></td></tr> <tr><td colspan="2" align="center"><input type="submit" value="Send Email" name="sendEmail" id="sendEmail"></td></tr> </table> </form> <body> </html> 

Я получил почту, но не смог найти никаких вложений. Кто-нибудь знает, что может быть неправильным?

Вот адрес электронной почты, который я получил по почте:

  MIME-Version: 1.0 Content-Type: multipart / mixed; 
 граница = "== Multipart_Boundary_x2d454346f03d2c19cfefc838ce4d8623x"

 Это многокомпонентное сообщение в формате MIME.

 - == Multipart_Boundary_x2d454346f03d2c19cfefc838ce4d8623x Content-Type: text / html;  кодировка = "ISO-8859-1"
 Content-Transfer-Encoding: 7 бит

 ds fsdfsdfsdfsdfsdfsdfsf sffdfsdfsdfs fsdfdf sdf s

 - == Multipart_Boundary_x2d454346f03d2c19cfefc838ce4d8623x Content-Type: {"application / octet-stream"};  имя = "/ TMP / phpHFTvAw"
 Content-Disposition: вложение;  имя файла = "Lighthouse.jpg"
 Content-Transfer-Encoding: base64




 - == Multipart_Boundary_x2d454346f03d2c19cfefc838ce4d8623x Content-Type: {"application / octet-stream"};  имя = "/ TMP / phpyX67HR"
 Content-Disposition: вложение;  имя файла = "Penguins.jpg"
 Content-Transfer-Encoding: base64




 - == Multipart_Boundary_x2d454346f03d2c19cfefc838ce4d8623x

Related of "Отправка нескольких вложений по электронной почте с помощью PHP"

Я предлагаю использовать PHPMailer для отправки писем с прикреплениями:

 <?php require 'PHPMailerAutoload.php'; // If this file is not located in the same directory, use __DIR__ . "/path/to/PHPMailerAutoload.php" $mail = new PHPMailer; $mail->From = 'from@example.com'; $mail->FromName = 'Mailer'; $mail->addAddress('joe@example.net', 'Joe User'); // Add a recipient $mail->addAddress('ellen@example.com'); // Name is optional $mail->addReplyTo('info@example.com', 'Information'); $mail->addCC('cc@example.com'); $mail->addBCC('bcc@example.com'); $mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name $mail->isHTML(true); // Set email format to HTML $mail->Subject = 'Here is the subject'; $mail->Body = 'This is the HTML message body <b>in bold!</b>'; $mail->AltBody = 'This is the body in plain text for non-HTML mail clients'; if(!$mail->send()) { echo 'Message could not be sent.'; echo 'Mailer Error: ' . $mail->ErrorInfo; } else { echo 'Message has been sent'; } ?> 

Скачать и документацию: здесь .

Ответ

Есть несколько проблем с вашим кодом, который я подробно описал ниже.

  • Линейные окончания

     $headers = 'From:'. $from . "\r\n"; $headers .= "Bcc:". $bcc . "\r\n"; ... // headers for attachment $headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"{$mime_boundary}\""; // multipart boundary $message = "This is a multi-part message in MIME format.\n\n" . "--{$mime_boundary}\n" . "Content-Type: text/html; charset=\"iso-8859-1\"\n" . "Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n"; $message .= "--{$mime_boundary}\n"; 

    Строки в сообщениях электронной почты разделены последовательностями CRLF ( \r\n ). Неясно, преобразует ли функция mail() \n в \r\n или нет, но учитывая, что ваши заголовки From: и Bcc: используют \r\n , они, вероятно, должны использовать их. Ваш вывод также указывает на то, что окончание строк, возможно, отсутствует или искажено.

    Из руководства PHP :

    Если сообщения не получены, попробуйте использовать только LF (\ n). Некоторые почтовые агенты Unix (в частности, qmail ) автоматически заменяют LF CRLF (что приводит к удвоению CR, если используется CRLF). Это должно быть последним средством, поскольку оно не соответствует »RFC 2822 .

  • Синтаксис заголовка

     $message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$files[$x]\"\n" . 

    Удалите фигурные скобки и кавычки:

     $message .= "Content-Type: application/octet-stream\n" . " name=\"$files[$x]\"\n" . 

    Кроме того, параметр name устарел в пользу параметра filename в заголовке Content-Disposition . Если вы хотите сохранить его для некоторой обратной совместимости, вы должны удалить из него путь. (Ваш вывод указывает, что вы используете tmp_name а не name ).

  • Разделители

     $message .= "--{$mime_boundary}\n"; // preparing attachments for($x=0;$x<count($files);$x++){ ... $message .= /* body part */; $message .= "--{$mime_boundary}\n"; } 

    Обратите внимание, что конечный разделитель должен иметь две концевые тире. Вставьте разделительные разделители в начале цикла и добавьте разделитель закрытия после цикла:

     // preparing attachments for($x=0;$x<count($files);$x++){ $message .= "--{$mime_boundary}\n"; ... $message .= /* body part */; } $message .= "--{$mime_boundary}--\n"; 

    См. Раздел синтаксиса электронной почты ниже.

  • Длина линии

     $k = 100; ... while($i<$count){ $bcc .= $toEmails[$i].","; if($j==$k || $i==$count-1){ ... $headers .= "Bcc:". $bcc . "\r\n"; в $k = 100; ... while($i<$count){ $bcc .= $toEmails[$i].","; if($j==$k || $i==$count-1){ ... $headers .= "Bcc:". $bcc . "\r\n"; 

    Обратите внимание, что в сообщениях электронной почты существуют ограничения длины строки. RFC 5322 :

      ... Каждая строка символов ДОЛЖНА быть не более
        998 символов, и ДОЛЖНО быть не более 78 символов, исключая
        CRLF.
    

    Возможно, вам захочется вырезать вашу Bcc короче или ввести FWS (Folding White Space) :

     $bcc .= $toEmails[$i].",\r\n "; /* FWS */ 
  • Другие вопросы

    Некоторые дополнительные проблемы или уведомления, которые могут быть полезными или могут быть полезными:


     foreach($_FILES['uploadEmail']['error'] as $key=>$value){ if(!$_FILES['uploadEmail']['error'][$key]){ 

    Последняя строка такая же, как:

      if(!$value){ 

     $target_path = ""; $target_path = $target_path . basename( $_FILES['uploadEmail']['name'][$key]); 

    Я предполагаю, что $target_path должен быть инициализирован каталогу загрузки.


     $toEmails = explode(",",$_POST['toEmail']); 

    Как правило, вы не должны позволять случайным пользователям предоставлять исходящие адреса электронной почты, но я подозреваю, что это внутреннее приложение для доверенных пользователей.


Синтаксис электронной почты

Это отрывок из того, как выглядит структура тела сообщений с несколькими частями в соответствии с RFC 2046. (Синтаксис BNF, несколько упрощен.)

 multipart-body: = [преамбула CRLF]
                   пограничная граница CRLF
                   инкапсуляция тела-части *
                   крупный ограничитель
                   [Эпилог CRLF]

 граница границы раздела: = "-"

 body-part: = MIME-частичные заголовки [CRLF * OCTET]

 инкапсуляция: = разделитель
                  CRLF часть тела

 разделитель: = граница CRLF

 close-delimiter: = разделитель "-"

Рекомендации

  • Формат интернет-сообщений RFC 2822 (Устаревший по RFC 5322)
  • Формат интернет-сообщений RFC 5322
  • RFC 2045 (MIME) Часть первая: формат интернет-сообщений
  • RFC 2046 (MIME) Часть вторая: Типы носителей