VPS网站使用PHPMailer发信报错无法连接SMTP主机如何解决
PHPMailer连接SMTP失败报错排查方案
你遇到的SMTP Error: Could not connect to SMTP host是PHPMailer最常见的连接层错误,本质是PHP进程根本没有成功连接到配置的SMTP服务器,按以下顺序排查即可,优先排查系统层配置,再检查代码问题:
1. 先修正错误的SMTP地址配置
你当前代码里填的$mail->Host = "mainserver.local"是最高概率的故障点:.local是内网保留域名,公网DNS无法解析,除非你手动在VPS的/etc/hosts文件里给这个域名绑定了邮件服务的IP,否则PHP从第一步解析地址就会失败。
- 如果网站和邮件服务跑在同一台VPS上,直接把Host改成
localhost即可,同机通信不需要绕公网,稳定性最高。 - 如果邮件服务跑在其他服务器,就填实际的邮件服务域名(比如
mail.managementskillsacademy.com,需要提前做好A记录解析到邮件服务器IP)或者公网IP。 - 不要上来就跑PHP代码,先在VPS命令行测连通性:
执行openssl s_client -connect 你配置的SMTP地址:465,如果能返回SSL证书信息、连接成功提示,说明地址端口是通的;如果直接超时、拒绝连接,就先解决网络层面的问题,不用改PHP代码。
2. 核对加密方式与端口匹配性,检查防火墙/服务监听状态
你当前配的SSL加密+465端口是标准的SMTPS配置,本身没有问题,但很多自建邮件服务的默认配置不一定开启这个组合:
- 如果465端口连不通,换STARTTLS加密+587端口的组合测试:把配置改成
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;,$mail->Port = 587,再测连通性。 - 不要用25端口发信:绝大多数云服务商默认封禁25端口防垃圾邮件,折腾没有意义。
- 检查两层防火墙:一是VPS系统自带的防火墙(ufw/firewalld/iptables),要放行你用的465/587端口;二是云服务商后台的安全组规则,也要放行对应端口的入站/出站规则。
- 确认邮件服务正常运行:执行
netstat -tulpn | grep -E '465|587',看有没有邮件服务(Postfix/Dovecot等)在监听对应端口,没监听的话先把邮件服务配置好再启动。
3. 修正代码里的低级问题
- 你代码里的Exception类引入拼写错误:
use PHPMailer\PHPMailer\Eception;少了个x,正确写法是use PHPMailer\PHPMailer\Exception;,这个问题虽然不直接导致连接失败,但会让异常捕获逻辑失效。 - 确认账号密码正确:如果是自建邮件服务,确认你填的
msacademy@managementskillsacademy.com账号确实存在、密码正确,且邮件服务开启了SMTP认证功能;如果是第三方邮箱,注意要填专门的客户端授权码,不是邮箱网页登录密码。
4. 排查SSL证书验证问题
如果命令行测端口能正常连通,但PHP代码还是报连接失败,基本是SSL证书校验的问题:
- 可以临时加如下配置测试能不能连通:
$mail->SMTPOptions = [ 'ssl' => [ 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true ] ]; - 加了配置就能发信的话,说明你邮件服务的SSL证书有问题(比如是自签名证书、证书域名和SMTP地址不匹配、证书过期),后续给邮件服务换个可信的SSL证书就行,不要长期关闭证书校验,存在被中间人攻击的风险。
修正后的可参考代码
<?php use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\SMTP; use PHPMailer\PHPMailer\Exception; // 修正之前的类名拼写错误 require "mail/src/PHPMailer.php"; require "mail/src/SMTP.php"; require "mail/src/Exception.php"; $mail = new PHPMailer(true); try { $mail->SMTPDebug = SMTP::DEBUG_SERVER; $mail->isSMTP(); $mail->Host = "localhost"; // 同机部署优先用localhost $mail->SMTPAuth = true; $mail->Username = "msacademy@managementskillsacademy.com"; $mail->Password = "你的邮箱实际密码"; $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; $mail->Port = 465; // 465不通就换下面两行配置 // $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // $mail->Port = 587; // 仅临时测试证书问题用,修复证书后请删除 /* $mail->SMTPOptions = [ 'ssl' => [ 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true ] ]; */ $mail->setFrom("msacademy@managementskillsacademy.com", "Fahd Abrah"); $mail->addAddress("msacademy@managementskillsacademy.com"); $mail->isHTML(true); $mail->CharSet = "UTF-8"; $mail->Subject = "Thanks for registering"; $mail->Body = "Thank you so <b>much</b>"; $mail->AltBody = "Thank you so much"; $mail->send(); echo "邮件发送成功"; } catch (Exception $e) { echo "Message could not be sent. Error: " . $mail->ErrorInfo; }
排查的时候严格按顺序来:先确认网络连通、服务正常,再调代码,80%的这类问题都是地址填错、端口没开、防火墙挡了这类系统层问题,和PHPMailer本身没关系。
内容的提问来源于stack exchange,提问作者Mohammed Fahd
相关产品推荐
相关产品推荐

