PHPMailer中filter_input处理非英文字符乱码问题求助
问题分析
你的核心问题是:FILTER_SANITIZE_FULL_SPECIAL_CHARS会将瑞典语特殊字符(ö、ä、å等)转成HTML实体(如ä、å),而纯文本邮件无法解析这些实体,导致显示异常;但直接使用$_POST又存在安全风险(邮件头注入、SQL注入)。另外你的PHPMailer代码存在一个明显bug:连续给Subject赋值两次,最终邮件主题会被消息内容覆盖,正文为空。
解决方案
分邮件发送、数据库存储两个场景分别处理安全和字符兼容问题:
一、邮件发送的安全处理(兼容特殊字符)
纯文本邮件不需要转义HTML实体,只需针对邮件头注入风险做过滤,同时确保UTF-8字符正常传输:
1. 替换过滤逻辑,保留原始UTF-8字符
移除FILTER_SANITIZE_FULL_SPECIAL_CHARS,改用自定义过滤防止邮件头注入(主要是移除主题中的换行/回车符,避免篡改邮件头):
// 获取POST数据并修剪首尾空白 $subject = isset($_POST['subject']) ? trim($_POST['subject']) : ''; $message = isset($_POST['message']) ? trim($_POST['message']) : ''; // 过滤主题中的换行、回车、空字符(防止邮件头注入) $subject = preg_replace('/[\r\n\x00\x0B]+/', '', $subject); // 消息保留正常换行,仅过滤危险空字符 $message = preg_replace('/[\x00\x0B]+/', '', $message);
2. 修正PHPMailer配置,指定UTF-8字符集
必须设置CharSet为UTF-8,同时修正主题/正文的赋值错误:
try { $mail = new PHPMailer(true); $mail->SetLanguage("fr", "phpmailer/language"); $mail->Encoding = "base64"; $mail->CharSet = 'UTF-8'; // 关键:确保特殊字符编码正确 $mail->ContentType = 'text/plain'; $mail->IsHTML(false); // 补充SMTP服务器配置(示例) $mail->isSMTP(); $mail->Host = 'smtp.yourserver.com'; $mail->SMTPAuth = true; $mail->Username = 'your_email@domain.com'; $mail->Password = 'your_smtp_password'; $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; $mail->Port = 587; // 设置发件人、收件人 $mail->setFrom('sender@domain.com', '发件人名称'); $mail->addAddress('recipient@domain.com', '收件人名称'); // 正确设置主题和正文 $mail->Subject = $subject; $mail->Body = $message; // 这里是Body,不是重复赋值Subject $mail->send(); } catch (Exception $e) { echo "发送失败: {$mail->ErrorInfo}"; }
二、MySQL存储的安全处理(防止SQL注入)
不要用字符过滤的方式防注入,**预处理语句(Prepared Statements)**是最安全的方案,同时能完整保留UTF-8字符:
PDO示例
try { // 建立PDO连接,指定utf8mb4字符集(支持所有UTF-8字符) $pdo = new PDO( 'mysql:host=localhost;dbname=your_database;charset=utf8mb4', 'db_username', 'db_password' ); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 预处理SQL语句 $stmt = $pdo->prepare("INSERT INTO messages (subject, message) VALUES (:subject, :message)"); // 绑定参数,自动处理转义 $stmt->bindParam(':subject', $subject, PDO::PARAM_STR); $stmt->bindParam(':message', $message, PDO::PARAM_STR); $stmt->execute(); } catch (PDOException $e) { echo "存储失败: " . $e->getMessage(); }
核心要点
- 邮件场景:纯文本不需要HTML实体转义,只需过滤邮件头注入风险,同时强制UTF-8编码。
- 数据库场景:预处理语句彻底解决SQL注入,无需额外字符转义,完美兼容特殊字符。
- 修正PHPMailer的赋值错误,避免主题被正文覆盖。
内容的提问来源于stack exchange,提问作者New-Girl
相关产品推荐
相关产品推荐

