使用PHP发送邮件附件问题:循环导致附件分开发送
解决PHP循环发送邮件时每个附件单独发一封的问题
我懂你现在的困扰——你的代码把邮件发送逻辑放进了循环里,所以每处理一个附件就发一封邮件,自然每封只有一个附件。要改成一封邮件带所有附件,只需要调整代码结构:把添加附件的逻辑放在循环内,而邮件发送的核心代码放在循环外就行。
推荐方案:用PHPMailer实现(更简洁可靠)
PHPMailer是PHP处理邮件的常用库,比原生mail()函数更易维护,也更不容易出MIME格式问题。下面是修改后的完整示例:
// 先确保你已经引入了PHPMailer的自动加载文件 require 'PHPMailer/src/PHPMailer.php'; require 'PHPMailer/src/SMTP.php'; require 'PHPMailer/src/Exception.php'; use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\SMTP; use PHPMailer\PHPMailer\Exception; // 初始化PHPMailer对象 $mail = new PHPMailer(true); try { // 配置SMTP服务器(根据你的邮件服务商调整) $mail->isSMTP(); $mail->Host = 'smtp.example.com'; $mail->SMTPAuth = true; $mail->Username = 'your-email@example.com'; $mail->Password = 'your-email-password'; $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; $mail->Port = 465; // 设置邮件基本信息(这些放在循环外面,只配置一次) $mail->setFrom('sender@example.com', 'Sender Name'); $mail->addAddress('recipient@example.com', 'Recipient Name'); $mail->Subject = '邮件主题:包含多个附件'; $mail->Body = '这是邮件正文,里面包含你上传的所有附件'; // 处理上传的多个附件(循环里只添加附件,不发送) $otherdocCount = count($_FILES['otherdoc']['name']); for ($i = 0; $i < $otherdocCount; $i++) { $tmpFilePath = $_FILES['otherdoc']['tmp_name'][$i]; $fileName = $_FILES['otherdoc']['name'][$i]; // 验证文件是否成功上传 if (file_exists($tmpFilePath) && is_uploaded_file($tmpFilePath)) { // 添加附件到邮件 $mail->addAttachment($tmpFilePath, $fileName); } else { // 可选:处理上传失败的文件 echo "文件 {$fileName} 上传失败,已跳过"; } } // 循环结束后,只发送一次邮件 $mail->send(); echo '邮件发送成功,所有附件已包含在内'; } catch (Exception $e) { echo "邮件发送失败:{$mail->ErrorInfo}"; }
如果你坚持用原生mail()函数
原生函数需要手动构建MIME多部分邮件,相对繁琐,这里给个核心逻辑示例:
// 邮件基本信息 $to = 'recipient@example.com'; $subject = '带多个附件的邮件'; $message = '邮件正文内容'; $boundary = md5(time()); // 构建邮件头 $headers = "From: sender@example.com\r\n"; $headers .= "MIME-Version: 1.0\r\n"; $headers .= "Content-Type: multipart/mixed; boundary=\"{$boundary}\"\r\n"; // 构建邮件正文部分 $mailContent = "--{$boundary}\r\n"; $mailContent .= "Content-Type: text/plain; charset=utf-8\r\n"; $mailContent .= "Content-Transfer-Encoding: 7bit\r\n\r\n"; $mailContent .= $message . "\r\n\r\n"; // 循环添加附件到邮件内容 $otherdocCount = count($_FILES['otherdoc']['name']); for ($i = 0; $i < $otherdocCount; $i++) { $tmpFilePath = $_FILES['otherdoc']['tmp_name'][$i]; $fileName = $_FILES['otherdoc']['name'][$i]; if (file_exists($tmpFilePath) && is_uploaded_file($tmpFilePath)) { $fileContent = file_get_contents($tmpFilePath); $fileContent = chunk_split(base64_encode($fileContent)); $mailContent .= "--{$boundary}\r\n"; $mailContent .= "Content-Type: application/octet-stream; name=\"{$fileName}\"\r\n"; $mailContent .= "Content-Disposition: attachment; filename=\"{$fileName}\"\r\n"; $mailContent .= "Content-Transfer-Encoding: base64\r\n\r\n"; $mailContent .= $fileContent . "\r\n\r\n"; } } // 结束边界 $mailContent .= "--{$boundary}--"; // 发送邮件(只调用一次) if (mail($to, $subject, $mailContent, $headers)) { echo '邮件发送成功'; } else { echo '邮件发送失败'; }
关键注意点
- 一定要把邮件发送的代码(比如
$mail->send()或者mail())放在循环外面,循环里只负责收集/添加附件 - 记得验证上传文件的有效性(
is_uploaded_file()),避免处理非法文件 - 如果用PHPMailer,确保已经正确安装和引入库(可以通过Composer安装:
composer require phpmailer/phpmailer)
内容的提问来源于stack exchange,提问作者Akash M
相关产品推荐
相关产品推荐

