菜鸟科技网

PHP邮件附件上传如何实现?

使用 PHP 内置的 mail() 函数

这种方法最底层,可以让你完全控制邮件的构建过程,但代码相对繁琐,容易出错。

PHP邮件附件上传如何实现?-图1
(图片来源网络,侵删)

核心原理

发送带附件的邮件,本质上是在邮件的头部添加特殊的 Content-TypeContent-Disposition 信息,用以声明邮件包含多个部分(文本内容和附件),这需要使用 MIME (Multipurpose Internet Mail Extensions) 协议。

关键步骤

  1. 定义邮件头:特别是 MIME-VersionContent-TypeContent-Transfer-Encoding
  2. 构建邮件主体:使用 boundary(边界字符串)来分隔邮件的不同部分(如文本和附件)。
  3. 添加文本部分:在 boundary 后添加邮件的正文内容。
  4. 添加附件部分:为每个附件重复以下步骤:
    • boundary 后添加附件的头信息。
    • 读取附件文件的内容。
    • 进行 Base64 编码(因为邮件不能直接传输二进制数据)。
    • 添加编码后的内容。
  5. 结束邮件:以 --boundary-- 标志邮件的结束。

完整示例代码

<?php
// 邮件接收者
$to = 'recipient@example.com';
// 邮件主题
$subject = '这是一封带附件的测试邮件';
$message = '您好,<br><br>这封邮件包含一个附件,请查收。<br><br>谢谢!';
// 文件路径
$filename = 'test.pdf'; // 假设附件是当前目录下的 test.pdf
// 读取文件内容
$file_content = file_get_contents($filename);
// 对文件内容进行 base64 编码
$encoded_content = chunk_split(base64_encode($file_content));
// 定义一个随机字符串作为 boundary
$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";
// 邮件主体
$body = "--$boundary\r\n";
$body .= "Content-Type: text/html; charset=UTF-8\r\n";
$body .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
$body .= "$message\r\n\r\n";
// 附件部分
$body .= "--$boundary\r\n";
$body .= "Content-Type: application/pdf; name=\"$filename\"\r\n"; // 根据文件类型设置 Content-Type
$body .= "Content-Transfer-Encoding: base64\r\n";
$body .= "Content-Disposition: attachment; filename=\"$filename\"\r\n\r\n";
$body .= "$encoded_content\r\n\r\n";
// 结束 boundary
$body .= "--$boundary--";
// 发送邮件
if (mail($to, $subject, $body, $headers)) {
    echo "邮件发送成功!";
} else {
    echo "邮件发送失败!";
}
?>

代码解析:

  • chunk_split(base64_encode($file_content)): Base64 编码后的字符串很长,chunk_split 会将其分割成每76个字符一行,这符合 MIME 标准。
  • Content-Type: multipart/mixed: 声明邮件包含多个不同类型的部分。
  • boundary: 一个独特的字符串,用于在邮件流中标记不同部分的开始和结束。
  • Content-Disposition: attachment: 这是告诉邮件客户端(如 Outlook, Gmail)这是一个需要下载的附件的关键指令。

使用 PHPMailer 库(强烈推荐)

使用 PHPMailer 可以让你从繁琐的邮件头构建中解放出来,代码更简洁、更安全、更易于维护,PHPMailer 处理了所有的编码和 MIME 格式化工作。

为什么推荐 PHPMailer?

  • 简单易用:提供清晰的面向对象接口。
  • 功能强大:支持 SMTP 认证、HTML 邮件、附件、图片嵌入等。
  • 安全可靠:能有效防止邮件注入等安全问题。
  • 兼容性好:处理了各种服务器环境下的兼容性问题。

步骤 1:安装 PHPMailer

最简单的方式是使用 Composer:

PHP邮件附件上传如何实现?-图2
(图片来源网络,侵删)
composer require phpmailer/phpmailer

步骤 2:编写发送带附件的邮件代码

<?php
// 引入 PHPMailer 的自动加载文件
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'vendor/autoload.php'; // 确保路径正确
// 创建一个 PHPMailer 实例
$mail = new PHPMailer(true); // `true` 启用异常处理
try {
    // 服务器设置
    // $mail->isSMTP();                              // 使用 SMTP
    // $mail->Host       = 'smtp.example.com';       // SMTP 服务器地址
    // $mail->SMTPAuth   = true;                     // 启用 SMTP 认证
    // $mail->Username   = 'user@example.com';       // SMTP 用户名
    // $mail->Password   = 'secret';                 // SMTP 密码
    // $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; // 启用 TLS/SSL 加密
    // $mail->Port       = 465;                      // SMTP 端口
    // 如果不需要通过外部 SMTP 服务器发送(本地测试或使用 sendmail),可以注释掉上面的 SMTP 配置。
    // 大多数虚拟主机/服务器默认支持 PHP 的 mail() 函数。
    $mail->isMail(); // 使用 PHP 的 mail() 函数发送
    // 收件人
    $mail->setFrom('from@example.com', '发件人名称');
    $mail->addAddress('recipient@example.com', '收件人名称'); // 添加一个收件人
    // 附件
    // 方法1: 添加一个来自文件的附件
    $mail->addAttachment('test.pdf', '我的文档.pdf'); // 可选参数:附件的别名(新文件名)
    // 方法2: 添加一个来自字符串的附件
    // $pdfData = file_get_contents('another_file.pdf');
    // $mail->addStringAttachment($pdfData, 'another_file.pdf');
    // 内容
    $mail->isHTML(true); // 设置邮件格式为 HTML
    $mail->Subject = '使用 PHPMailer 发送带附件的邮件';
    $mail->Body    = '您好,<br>这封邮件是使用 PHPMailer 发送的,并且包含一个 PDF 附件。';
    $mail->AltBody = '这是纯文本邮件内容,用于不支持 HTML 的邮件客户端。';
    $mail->send();
    echo '邮件发送成功!';
} catch (Exception $e) {
    echo "邮件发送失败: {$mail->ErrorInfo}";
}
?>

代码解析:

  • use PHPMailer\PHPMailer\PHPMailer;: 引入 PHPMailer 类。
  • $mail = new PHPMailer(true);: 创建实例,并启用异常捕获。
  • $mail->addAttachment('path/to/file.pdf', 'new_name.pdf');: 这是添加附件的核心方法。
    • 第一个参数是文件的本地路径。
    • 第二个参数是可选的,可以指定附件在邮件中显示的文件名。
  • $mail->send(): 执行发送操作。
  • try...catch: 使用异常处理来捕获发送过程中可能出现的错误,并通过 $mail->ErrorInfo 获取错误信息。

总结与对比

特性 PHP mail() 函数 PHPMailer 库
易用性 ,需要手动构建复杂的 MIME 头。 ,提供简单直观的方法,如 addAttachment()
灵活性 ,可以对邮件头进行完全控制。 ,支持 SMTP、HTML、附件、图片嵌入等高级功能。
可靠性 ,容易因编码错误导致邮件格式不正确,被当成垃圾邮件。 ,经过充分测试,能正确处理各种编码和边界情况。
安全性 ,需要开发者自己小心处理邮件注入等问题。 ,内置了对邮件注入等常见攻击的防护。
依赖 无(PHP 内置) 需要通过 Composer 安装(推荐)或手动下载文件。

对于任何生产环境或稍微复杂一点的邮件发送需求,强烈推荐使用 PHPMailer,它能让你把精力集中在业务逻辑上,而不是底层的邮件协议细节,只有在进行非常简单的、不需要附件的测试时,才考虑直接使用 mail() 函数。

分享:
扫描分享到社交APP
上一篇
下一篇