
php 原生 `mail()` 函数处理附件时易因临时文件丢失、编码错误或 mime 结构不规范导致附件随机缺失;推荐改用成熟稳定的 phpmailer 库,它自动处理边界生成、编码、路径验证与错误反馈,大幅提升附件送达可靠性。
在您提供的代码中,附件失败的根本原因并非逻辑偶然,而是由多个系统级脆弱点共同导致:
- ❌ $_FILES["attachment"]["tmp_name"] 未校验上传状态:未检查 $_FILES["attachment"]["error"] === UPLOAD_ERR_OK,上传失败(如超限、中断)时 $attachment 为空字符串,但后续仍尝试移动/读取,造成静默失败;
- ❌ 临时文件被提前清理:move_uploaded_file() 缺失,直接使用 $_FILES["attachment"]["tmp_name"] 依赖 PHP 的临时目录生命周期——该文件可能在脚本结束前已被清理(尤其在高并发或短超时时);
- ❌ MIME 边界与换行符不兼容:手动拼接的 \n 在 Windows 环境下可能被 SMTP 中继截断,且 Content-Disposition 中换行位置错误(缺少空行),违反 RFC 2046;
- ❌ 无错误反馈机制:@mail() 屏蔽了所有警告,$mail 返回 true 仅表示“投递到本地 MTA 成功”,不代表邮件真正发出或附件被解析。
✅ 正确解法:弃用原生 mail(),采用 PHPMailer —— 它内置健壮的附件处理流程:
✅ 快速集成步骤(推荐 Composer 方式)
composer require phpmailer/phpmailer
✅ 安全可靠的发送代码(含完整错误处理)
5 * 1024 * 1024) {
die("不支持的文件类型或大小超出限制");
}
// 3. 移动临时文件到安全位置(避免被清理)
$uploadDir = __DIR__ . '/uploads/';
if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true);
$safePath = $uploadDir . uniqid() . '_' . basename($file['name']);
if (!move_uploaded_file($file['tmp_name'], $safePath)) {
die("无法保存上传文件");
}
try {
$mail = new PHPMailer(true);
$mail->setFrom($_POST['email'], $_POST['First'] . ' ' . $_POST['Last']);
$mail->addAddress('recipient@example.com'); // 替换为目标邮箱
$mail->addAttachment($safePath); // 自动处理编码与 MIME
$mail->isHTML(true);
$mail->Subject = 'Mail From Applied Candidate';
$mail->Body = <<Candidate Information
Name: {$_POST['First']} {$_POST['Last']}
Email: {$_POST['email']}
立即学习“PHP免费学习笔记(深入)”;
Phone: {$_POST['phone']}
Address: {$_POST['address']}
Position: {$_POST['position']}
Experience: {$_POST['experience']} years
HTML;
$mail->send();
echo "✅ 邮件发送成功!";
// 清理临时文件(发送成功后)
@unlink($safePath);
} catch (Exception $e) {
error_log("PHPMailer Error: " . $e->getMessage());
echo "❌ 邮件发送失败:{$mail->ErrorInfo}";
}
}
?>⚠️ 关键注意事项
- 永远不要跳过 $_FILES['xxx']['error'] 检查:这是判断上传是否真实的唯一可靠依据;
- 必须调用 move_uploaded_file():将文件移出临时目录,否则其生命周期不可控;
- 禁用 @ 符号抑制错误:它掩盖了致命问题,应通过异常或 error_get_last() 主动捕获;
- 生产环境务必配置 SMTP(如 Gmail、SendGrid):原生 mail() 依赖本地 sendmail,极易被标记为垃圾邮件;
- 上传目录需设置 Web 不可执行权限:防止恶意用户上传 .php 文件并直接访问。
? 提示:若无法使用 Composer,可下载 PHPMailer Release 并手动引入 src/PHPMailer.php、src/Exception.php、src/SMTP.php 三个文件。
采用 PHPMailer 后,附件丢失问题将彻底消失——因为它将 MIME 构建、Base64 编码、文件流读取、错误分类全部封装为原子操作,开发者只需专注业务逻辑。











