PHP多附件邮件发送异常:仅收到最后一个附件求助
问题:PHP发送多附件邮件仅收到最后一个文件
通过POST API(Postman form-data提交)接收4个附件,调用PHP的mail()函数发送邮件,但仅能收到最后一个附件。已开启错误报告:
error_reporting(-1); ini_set('display_errors', 'On');
错误日志无报错,原代码存在结构逻辑问题,导致邮件内容被覆盖、MIME格式混乱。
问题根源
- 重复生成MIME边界:每个附件处理时都重新创建新的MIME边界,多次向
$headers添加MIME头部,破坏邮件结构。 - 覆盖消息体变量:处理第二个附件时用
$message =直接赋值,覆盖了之前的文本内容和第一个附件数据,最终仅保留最后一个附件。 - 不符合MIME规范:多附件邮件需使用同一个边界分隔所有内容(文本+多个附件),而非每个附件单独创建边界。
修正后的完整代码
<?php error_reporting(-1); ini_set('display_errors', 'On'); if ($_POST) { $name = "Name goes here"; $email = "seshuvardhan456@gmail.com"; $to = "$name <$email>"; $from = "Gyan-Shah"; $subject = "Here is your attachment"; // 构建文本内容 $mainMessage = "Hi,\nBelow are the Details:\n" . "Name: '" . $_POST['fullname'] . "'\n" . "Date Of Birth: '" . $_POST['dob'] . "'\n" . "Phone Number: '" . $_POST['phone_number'] . "'\n" . "Email: '" . $_POST['email'] . "'\n" . "Address: '" . $_POST['address'] . "'\n" . "Father Name: '" . $_POST['father_name'] . "'\n" . "Mother Name: '" . $_POST['mother_name'] . "'\n" . "Work Experience: '" . $_POST['work_experience'] . "'\n" . "Education: '" . $_POST['education'] . "'\n" . "Skills: '" . $_POST['skills'] . "'\n"; // 初始化邮件头部与唯一MIME边界 $semi_rand = md5(time()); $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x"; $headers = "From: $from\r\n"; $headers .= "MIME-Version: 1.0\r\n"; $headers .= "Content-Type: multipart/mixed;\r\n boundary=\"{$mime_boundary}\""; // 初始化消息体:文本部分 $message = "This is a multi-part message in MIME format.\r\n\r\n"; $message .= "--{$mime_boundary}\r\n"; $message .= "Content-Type: text/plain; charset=\"iso-8859-1\"\r\n"; $message .= "Content-Transfer-Encoding: 7bit\r\n\r\n"; $message .= $mainMessage . "\r\n\r\n"; // 处理第一个附件:照片 if (isset($_FILES['photo']) && $_FILES['photo']['error'] == UPLOAD_ERR_OK) { $tmp_name = $_FILES['photo']['tmp_name']; $name = $_FILES['photo']['name']; $size = $_FILES['photo']['size']; $type = $_FILES['photo']['type']; $handle = fopen($tmp_name, "r"); $content = fread($handle, $size); fclose($handle); $data = chunk_split(base64_encode($content)); $message .= "--{$mime_boundary}\r\n"; $message .= "Content-Type: {$type};\r\n name=\"{$name}\"\r\n"; $message .= "Content-Disposition: attachment;\r\n filename=\"{$name}\"\r\n"; $message .= "Content-Transfer-Encoding: base64\r\n\r\n"; $message .= $data . "\r\n\r\n"; } // 处理第二个附件:护照首页 if (isset($_FILES['passport_front']) && $_FILES['passport_front']['error'] == UPLOAD_ERR_OK) { $tmp_name_p_f = $_FILES['passport_front']['tmp_name']; $name_p_f = $_FILES['passport_front']['name']; $size_p_f = $_FILES['passport_front']['size']; $type_p_f = $_FILES['passport_front']['type']; $handle_p_f = fopen($tmp_name_p_f, "r"); $content_p_f = fread($handle_p_f, $size_p_f); fclose($handle_p_f); $data_p_f = chunk_split(base64_encode($content_p_f)); $message .= "--{$mime_boundary}\r\n"; $message .= "Content-Type: {$type_p_f};\r\n name=\"{$name_p_f}\"\r\n"; $message .= "Content-Disposition: attachment;\r\n filename=\"{$name_p_f}\"\r\n"; $message .= "Content-Transfer-Encoding: base64\r\n\r\n"; $message .= $data_p_f . "\r\n\r\n"; } // 处理剩余两个附件(请替换为实际字段名) // if (isset($_FILES['xxx']) && $_FILES['xxx']['error'] == UPLOAD_ERR_OK) { // // 重复上述附件处理逻辑 // } // 结束MIME边界 $message .= "--{$mime_boundary}--\r\n"; // 发送邮件 if (mail($to, $subject, $message, $headers)) { echo "The email was sent."; } else { echo "There was an error sending the mail."; } } ?>
关键改进说明
- 统一MIME边界:仅生成一个唯一边界,所有内容通过该边界分隔,符合邮件MIME规范。
- 追加消息体:使用
$message .=追加附件内容,避免覆盖之前的文本和附件数据。 - 规范换行符:使用
\r\n作为邮件头部和消息体的换行符,符合RFC邮件标准。 - 上传校验:通过
UPLOAD_ERR_OK判断文件是否上传成功,避免处理无效文件。 - 模块化扩展:每个附件的处理逻辑独立,方便添加更多附件。
内容的提问来源于stack exchange,提问作者seshuvardhan P
相关产品推荐
相关产品推荐

