PHP 安全电子邮件发送指南
                           
天天向上
发布: 2025-03-21 00:03:39

原创
308 人浏览过

在 PHP 中发送电子邮件时,安全性是一个重要的考量因素。为了防止邮件被拦截、伪造或被用于恶意目的,需要采用一些安全措施。本文将介绍 PHP 发送安全电子邮件的最佳实践,包括 防止伪造、防止垃圾邮件、使用加密协议、安全存储凭据 以及 防止邮件头注入 等内容。


1. 避免邮件头注入攻击

邮件头注入(Email Header Injection)是一种攻击方式,攻击者可以通过未过滤的用户输入,在 mail() 函数的 headers 参数中插入额外的邮件头,从而发送垃圾邮件或进行钓鱼攻击。

不安全代码示例

$to = $_POST['email']; // 用户提供的邮箱(不安全)
$subject = "欢迎邮件";
$message = "欢迎注册!";
$headers = "From: admin@example.com\r\n";
$headers .= "Reply-To: admin@example.com\r\n";
$headers .= "CC: " . $_POST['cc'] . "\r\n"; // 用户输入(不安全)

mail($to, $subject, $message, $headers);

问题:

  • $_POST['email']$_POST['cc'] 可能被恶意用户插入换行符,从而添加额外的 CCBCCTo 字段,导致垃圾邮件攻击。

安全解决方案

  • 验证邮箱格式
  • 移除换行符
  • 使用 filter_var() 过滤输入

安全代码示例:

$to = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
$cc = filter_var($_POST['cc'], FILTER_VALIDATE_EMAIL);

if ($to && $cc) {
    $subject = "欢迎邮件";
    $message = "欢迎注册!";
    $headers = "From: admin@example.com\r\n";
    $headers .= "Reply-To: admin@example.com\r\n";
    $headers .= "CC: " . $cc . "\r\n";

    mail($to, $subject, $message, $headers);
}

2. 使用 SMTP 代替 mail()

PHP 内置的 mail() 不支持身份验证和加密,容易被垃圾邮件过滤。推荐使用 SMTP + TLS/SSL,例如 PHPMailerSwiftMailer

PHPMailer 发送安全电子邮件

安装 PHPMailer

composer require phpmailer/phpmailer

SMTP 方式发送邮件(支持 TLS/SSL 加密):

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require 'vendor/autoload.php';

$mail = new PHPMailer(true);

try {
    $mail->isSMTP();
    $mail->Host       = 'smtp.example.com'; // 你的 SMTP 服务器
    $mail->SMTPAuth   = true;
    $mail->Username   = 'your-email@example.com'; // SMTP 用户名
    $mail->Password   = 'your-email-password'; // SMTP 密码
    $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // 加密方式 (TLS)
    $mail->Port       = 587; // SMTP 端口 (TLS: 587, SSL: 465)

    // 发件人
    $mail->setFrom('your-email@example.com', 'Your Name');
    $mail->addAddress('recipient@example.com', 'Recipient Name');

    // 邮件内容
    $mail->isHTML(true);
    $mail->Subject = '安全邮件示例';
    $mail->Body    = '<p>这是一封安全的测试邮件。</p>';
    $mail->AltBody = '这是一封安全的测试邮件。';

    $mail->send();
    echo '邮件已发送';
} catch (Exception $e) {
    echo "邮件发送失败: {$mail->ErrorInfo}";
}

SMTP 安全性

  • 避免存储 SMTP 凭据在代码中,可使用 .env 或环境变量:
  putenv("SMTP_USERNAME=your-email@example.com");
  putenv("SMTP_PASSWORD=your-email-password");
  $mail->Username = getenv("SMTP_USERNAME");
  $mail->Password = getenv("SMTP_PASSWORD");
  • 启用 SPF、DKIM、DMARC 记录,防止邮件被标记为垃圾邮件(见第 4 部分)。

3. 发送加密邮件

为了保护邮件内容的隐私,可以使用 OpenPGP(PGP 加密)S/MIME 加密

使用 PHPMailer 发送 PGP 加密邮件

$mail->Body = openssl_encrypt('这是一封加密邮件', 'AES-256-CBC', 'your-secret-key', 0, 'your-iv');

此方法可以加密邮件正文,接收方需解密后阅读。


4. 保护邮件不被垃圾邮件过滤

许多邮件被误判为垃圾邮件,可以通过以下方法 提高送达率

(1) 配置 SPF 记录

SPF(Sender Policy Framework) 允许管理员指定哪些邮件服务器有权限代表你的域发送邮件。

📌 示例 SPF 记录(DNS TXT 记录):

v=spf1 include:_spf.example.com ~all

~all 表示软失败(SoftFail),-all 表示硬失败(HardFail)。

(2) 配置 DKIM 记录

DKIM(DomainKeys Identified Mail)用于 数字签名邮件,确保邮件内容未被篡改。

📌 示例 DKIM 记录(DNS TXT 记录):

default._domainkey.example.com IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCS..."

配置后,需要在 邮件头 添加 DKIM 签名:

$mail->DKIM_domain = 'example.com';
$mail->DKIM_selector = 'default';
$mail->DKIM_private = '/path/to/private.key';
$mail->DKIM_passphrase = '';

(3) 配置 DMARC 记录

DMARC(Domain-based Message Authentication, Reporting & Conformance)结合 SPF 和 DKIM 进一步加强邮件安全。

📌 示例 DMARC 记录(DNS TXT 记录):

_dmarc.example.com IN TXT "v=DMARC1; p=reject; rua=mailto:report@example.com"

p=reject 表示拒绝所有未通过验证的邮件。


5. 发送安全附件

攻击者可能利用邮件附件传播病毒或恶意软件。因此:

  • 避免发送 .exe.bat.js 等可执行文件
  • 使用 PHPMailer 进行 MIME 类型检测

示例(发送 PDF 附件)

$mail->addAttachment('/path/to/document.pdf', '安全文档.pdf');

6. 发送安全 HTML 邮件

邮件内容应避免:

  • 未转义的用户输入
  • 嵌入 JavaScript
  • 外部加载不可信任资源

安全 HTML 邮件示例

$mail->Body = htmlspecialchars('<h1>欢迎</h1><p>这是一封安全邮件。</p>');

使用 htmlspecialchars() 防止 HTML 注入攻击。


总结

安全措施方案
防止邮件头注入过滤输入 (filter_var())
安全身份验证使用 SMTP (PHPMailerSwiftMailer)
防止垃圾邮件SPF、DKIM、DMARC
发送加密邮件PGP/S-MIME 加密
附件安全禁止可执行文件

推荐使用 PHPMailer + SMTP + SPF/DKIM/DMARC 来确保邮件安全!

更多详细内容请关注其他相关文章!

发表回复 0

Your email address will not be published. Required fields are marked *