У меня проблема с отправкой электронного письма с несколькими вложениями. Вот код:
<?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 = '[email protected]';
$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-версия: 1.0 Content-Type: составная / смешанная; граница = "== Multipart_Boundary_x2d454346f03d2c19cfefc838ce4d8623x" Это сообщение из нескольких частей в формате MIME. - == Multipart_Boundary_x2d454346f03d2c19cfefc838ce4d8623x Тип содержимого: text / html; charset = "iso-8859-1" Content-Transfer-Encoding: 7bit ds fsdfsdfsdfsdfsdfsdfsf sffdfsdfsdfs fsdfdf sdf s - == Multipart_Boundary_x2d454346f03d2c19cfefc838ce4d8623x Тип содержимого: {"application / octet-stream"}; name = "/ tmp / phpHFTvAw" Content-Disposition: вложение; filename = "Lighthouse.jpg" Кодировка передачи контента: base64 - == Multipart_Boundary_x2d454346f03d2c19cfefc838ce4d8623x Тип контента: {"application / octet-stream"}; name = "/ tmp / phpyX67HR" Content-Disposition: вложение; filename = "Penguins.jpg" Кодировка передачи содержимого: base64 - == Multipart_Boundary_x2d454346f03d2c19cfefc838ce4d8623x
Я предлагаю использовать 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 = '[email protected]';
$mail->FromName = 'Mailer';
$mail->addAddress('[email protected]', 'Joe User'); // Add a recipient
$mail->addAddress('[email protected]'); // Name is optional
$mail->addReplyTo('[email protected]', 'Information');
$mail->addCC('[email protected]');
$mail->addBCC('[email protected]');
$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
вероятно, они должны использовать то же самое. Ваш вывод также указывает, что окончания строки, возможно, отсутствуют или искажены.
Если сообщения не получены, попробуйте использовать только 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";
Обратите внимание, что в сообщениях электронной почты есть ограничения на длину строки. RFC 5322:
... Каждая строка символов ДОЛЖНА быть не более 998 символов, и ДОЛЖНЫ быть не более 78 символов, исключая CRLF.
Вы можете сократить ваши Bcc
короче или ввести FWS (складной пробел):
$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-part-headers [CRLF * OCTET] инкапсуляция: = разделитель CRLF часть тела разделитель: = CRLF-тире разделитель: = разделитель "-"