在 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']可能被恶意用户插入换行符,从而添加额外的CC、BCC或To字段,导致垃圾邮件攻击。
安全解决方案
- 验证邮箱格式
- 移除换行符
- 使用
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,例如 PHPMailer 或 SwiftMailer。
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 (PHPMailer、SwiftMailer) |
| 防止垃圾邮件 | SPF、DKIM、DMARC |
| 发送加密邮件 | PGP/S-MIME 加密 |
| 附件安全 | 禁止可执行文件 |
推荐使用 PHPMailer + SMTP + SPF/DKIM/DMARC 来确保邮件安全!
更多详细内容请关注其他相关文章!