PEAR Mail发送UTF-8字符异常求助:SMTP邮件非ASCII字符显示错误
问题描述
使用PEAR Mail包通过外部SMTP发送联系表单消息,网页采用UTF-8编码,表单变量回显显示正常,但国际字符(čšđž)无法正常发送——收件箱中邮件的Reply-To名称和正文显示异常,邮件头charset为ISO-8859-1。请问这是PEAR Mail还是SMTP服务商的问题?如何修复以在SMTP邮件头和正文中发送非ASCII字符?
相关代码:
//email send require_once "Mail.php"; require_once "Mail/mime.php"; $from = "<noreply@example.com>"; $to = "<inbox@example.com>"; $subject = "Message from form"; $text = $_POST["body"]; $replyTo = $_POST["senderName"] . " <" . $_POST["senderEmail"] . ">"; $mime = new Mail_mime(); $mime->setTXTBody($text); $body = $mime->get(); $host = "ssl://mail.censoredsmtpprovider.com"; $port = "465"; // 8465 can also be used. $username = "censored"; $password = "censored"; $headers = array ( /*'Content-Type' => 'text/plain; charset=UTF-8', TRIED THIS WITH NO EFFECT */ 'From' => $from, 'Reply-To' => $replyTo, 'To' => $to, 'Subject' => $subject); $headers = $mime->headers($headers); $smtp = Mail::factory('smtp', array ('host' => $host, 'port' => $port, 'auth' => true, 'username' => $username, 'password' => $password)); $mail = $smtp->send($to, $headers, $body);
我找到一个15年前的可能解决方案,但不确定如今是否仍适用。
解决方案
问题根源
这不是SMTP服务商的问题,是PEAR Mail_mime的默认配置和邮件头编码处理不到位导致的:
- Mail_mime默认使用ISO-8859-1编码生成邮件内容,UTF-8字符会被转码乱码
- 邮件头中的非ASCII字符(比如Reply-To里的用户名)必须按RFC 2047标准编码,直接插入UTF-8字符串会被邮件客户端解析错误
具体修复步骤
初始化Mail_mime时指定UTF-8编码
创建实例时传入编码参数,覆盖默认的ISO-8859-1编码邮件头中的非ASCII字段
使用Mail_mime::encodeHeader()方法对包含非ASCII字符的邮件头字段(如Reply-To的名称部分)编码,确保客户端能正确解析让Mail_mime自动生成正确的Content-Type头
无需手动添加Content-Type,通过$mime->headers()方法自动生成带UTF-8 charset的头信息
修改后的完整代码
//email send require_once "Mail.php"; require_once "Mail/mime.php"; $from = "<noreply@example.com>"; $to = "<inbox@example.com>"; $subject = "Message from form"; $text = $_POST["body"]; // 对Reply-To中的用户名进行RFC标准编码 $encodedSenderName = Mail_mime::encodeHeader($_POST["senderName"], 'UTF-8'); $replyTo = $encodedSenderName . " <" . $_POST["senderEmail"] . ">"; // 初始化Mail_mime时指定UTF-8编码 $mime = new Mail_mime(array('text_charset' => 'UTF-8', 'html_charset' => 'UTF-8')); $mime->setTXTBody($text); $body = $mime->get(); $host = "ssl://mail.censoredsmtpprovider.com"; $port = "465"; // 8465 can also be used. $username = "censored"; $password = "censored"; $headers = array ( 'From' => $from, 'Reply-To' => $replyTo, 'To' => $to, 'Subject' => $subject); // 自动生成带UTF-8 charset的邮件头 $headers = $mime->headers($headers); $smtp = Mail::factory('smtp', array ('host' => $host, 'port' => $port, 'auth' => true, 'username' => $username, 'password' => $password)); $mail = $smtp->send($to, $headers, $body);
关于旧解决方案的说明
15年前的解决方案核心思路(指定编码、编码邮件头)仍然适用,因为邮件编码的RFC标准没有本质变化。PEAR Mail虽维护频率低,但核心功能稳定,按规范调整配置即可解决问题。
内容的提问来源于stack exchange,提问作者Lagavulin16
相关产品推荐
相关产品推荐

