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('[email protected]'); // 替换为目标邮箱
$mail->addAttachment($safePath); // 自动处理编码与 MIME
$mail->isHTML(true);
$mail->Subject = 'Mail From Applied Candidate';
$mail->Body = <<<HTML
Candidate Information
Name: {$_POST['First']} {$_POST['Last']}
Email: {$_POST['email']}
立即学习“PHP免费学习笔记(深入)”;
Phone: {$_POST['phone']}