You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

网站HTML邮件表单附件无法正常送达问题求助

问题分析与修复方案

你的代码存在几个关键问题,这些是导致邮件被拒收、附件损坏的核心原因,以下是具体问题和修复方式:

1. 未定义邮件主题$subject

代码调用mail()函数时使用了$subject变量,但该变量从未赋值。空主题会触发多数邮件服务商的垃圾邮件过滤规则,这是Gmail拒收邮件的重要原因之一。

2. 缺失文件上传错误检查

没有验证文件上传是否成功,当文件上传失败(比如临时文件生成失败、文件大小超出服务器限制、用户未选择文件等),直接读取临时文件会得到空内容,导致附件变成0字节。必须检查$_FILES['userImages']['error']的值,只有等于UPLOAD_ERR_OK时,才说明上传成功。

3. 文件读取无错误处理

file_get_contents($tmpName)可能因权限问题、临时文件被清理等原因失败,此时$content为false,后续的base64编码会生成无效内容,造成附件损坏。需要添加读取失败的判断逻辑。

4. 邮件头格式不规范

  • 发件人名称未做MIME编码,如果用户输入的名称包含特殊字符(如逗号、引号、中文),会破坏邮件头结构,导致邮件解析异常。
  • Content-Disposition未指定filename参数,部分邮件客户端无法正确识别附件文件名,甚至无法解析附件。

5. 字符集与错误屏蔽问题

  • 使用iso-8859-1字符集无法支持多语言内容,建议改为UTF-8避免乱码。
  • @mail()屏蔽了所有错误,无法排查邮件发送失败的具体原因,不利于问题定位。

修复后的完整代码

<?php
// 调试阶段开启错误提示,上线后可关闭
error_reporting(E_ALL);
ini_set('display_errors', 1);

// 检查表单与文件是否正常提交
if (!isset($_POST['userName'], $_POST['userEmail'], $_FILES['userImages'])) {
    die('表单数据不完整');
}

$fileName = $_FILES['userImages']['name'];
$tmpName = $_FILES['userImages']['tmp_name'];
$fileError = $_FILES['userImages']['error'];
$name = trim($_POST['userName']);
$email = trim($_POST['userEmail']);
$subject = '用户提交的表单与附件'; // 定义邮件主题
$mailto = 'receiving@email.com';

// 检查文件上传是否成功
if ($fileError !== UPLOAD_ERR_OK) {
    $errorMsg = match($fileError) {
        UPLOAD_ERR_INI_SIZE => '上传文件超出服务器限制',
        UPLOAD_ERR_FORM_SIZE => '上传文件超出表单限制',
        UPLOAD_ERR_PARTIAL => '文件仅部分上传',
        UPLOAD_ERR_NO_FILE => '未选择上传文件',
        UPLOAD_ERR_NO_TMP_DIR => '服务器临时目录缺失',
        UPLOAD_ERR_CANT_WRITE => '文件写入失败',
        UPLOAD_ERR_EXTENSION => '文件上传被扩展拦截',
        default => '未知上传错误',
    };
    die('文件上传失败:' . $errorMsg);
}

// 读取文件内容并检查是否成功
$content = file_get_contents($tmpName);
if ($content === false) {
    die('无法读取上传文件');
}
$content = chunk_split(base64_encode($content));

$separator = md5(time());
$eol = "\r\n";

// 对发件人名称进行MIME编码,避免特殊字符破坏邮件头
$encodedFromName = mb_encode_mimeheader($name, 'UTF-8', 'B');
$headers = "From: {$encodedFromName} <{$email}>" . $eol;
$headers .= "MIME-Version: 1.0" . $eol;
$headers .= "Content-Type: multipart/mixed; boundary=\"{$separator}\"" . $eol;
$headers .= "This is a MIME encoded message." . $eol;

$composition = "\r\n\n\nName: {$name}\r\nEmail Address: {$email}";

$body = "--{$separator}" . $eol;
$body .= "Content-Type: text/plain; charset=\"UTF-8\"" . $eol;
$body .= "Content-Transfer-Encoding: 8bit" . $eol;
$body .= $composition . $eol;

$body .= "--{$separator}" . $eol;
// 使用图片对应的MIME类型,而非通用的application/octet-stream
$fileMime = mime_content_type($tmpName);
$body .= "Content-Type: {$fileMime}; name=\"{$fileName}\"" . $eol;
$body .= "Content-Transfer-Encoding: base64" . $eol;
$body .= "Content-Disposition: attachment; filename=\"{$fileName}\"" . $eol;
$body .= $content . $eol;
$body .= "--{$separator}--";

// 去掉@符号,保留错误提示便于调试
$mailSent = mail($mailto, $subject, $body, $headers);
if (!$mailSent) {
    die('邮件发送失败,请检查服务器邮件配置');
}

header('Location: /sent_confirmation.php');
exit;
?>

额外建议

  1. 改用专业邮件库:部分服务器的mail()函数默认配置受限,建议使用PHPMailer等库,它能更好地处理MIME邮件、SMTP认证,大幅降低被拒收概率。
  2. 调整文件大小限制:检查php.ini中的upload_max_filesize和post_max_size参数,确保满足用户上传图片的大小需求。
  3. 配置邮件认证记录:给发件域名设置SPF、DKIM、DMARC记录,提升邮件可信度,避免被标记为垃圾邮件。

内容的提问来源于stack exchange,提问作者Q-Tip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 00:23:20