PHPMailer / PHPMailer


PHPMailer / PHPMailer

 代码 问题54 拉取请求11 项目 0 Wiki 脉搏 图   
故障排除
FrançoisB编辑本页 on 12 Jan · 50修订版
 第9页

关于CVE 2016 10033和CVE 2016 10045漏洞
Gmail XOAUTH2使用Google API客户端
覆盖SMTP类
正在发送到列表
故障排除
疑难解答
教程
在XOAUTH2中使用Gmail
本地克隆此wiki


https://github.com/PHPMailer/PHPMailer.wiki.git
 在桌面克隆
解决PHPMailer问题

无论你遇到什么问题,首先确保你使用最新的PHPMailer。如果你的代码基于你在GitHub上的某个地方找到的例子,它很可能已过时 - 基于你的代码基于examples文件夹中的例子。大约90%的Stack Overflow的问题会犯这个错误。

加载类

使用作曲家

Composer节省了大量的工作 - 处理包依赖,更新和下载,并生成一个漂亮的自动加载器,所以你不必require自己类。通过composer加载是在项目中使用PHPMailer的首选方法。所有你需要做的是要求composer自动加载器:

require './vendor/autoload.php';
尤其重要的是,如果你使用XOAUTH2身份验证,因为它需要由作曲家满足的依赖类。默认情况下不包括依赖项,因为它们不是每个人都需要的,并且它们不在PHPMailer支持的旧版PHP上工作,因此您可以在PHPMailer composer.json文件的“suggest”部分找到它们。您应该将这些依赖项复制到您自己composer.json的require部分,然后composer update加载它们并将它们添加到您的自动加载器。

如果您不这样做,可能会看到以下错误:

致命 错误:类 '联赛\ OAuth2用户\客户端\供应商\谷歌' 不 发现 在 PHPMailer的/ get_oauth_token 。PHP的 上 线 24
要解决这个问题,请按照所述配置composer,或下载此类及其所有依赖项,并手动加载它们。

使用PHPMailer自己的自动加载器

不久之前,PHPMailer改变了它加载类的方式,使它更加兼容composer,许多框架和PHP PSR-0自动加载标准。注意,因为我们支持PHP回5.0版本,我们不能支持更新的PSR-4标准,也不能使用命名空间。以前,PHPMailer显式加载了SMTP类,如果您想提供自己的实现,这会导致问题。你可能已经看到过这样的老脚本:

需要 ' class.phpmailer.php “ ;
如果您这样做,SMTP发送将失败并出现Class 'SMTP' not found错误。您需要明确包含该class.smtp.php文件(请阅读README以获取您需要的文件的信息),或者使用推荐的方法使用composer或提供的自动加载器,如下所示:

需要 ' PHPMailerAutoload.php “ ;
启用调试输出

如果您使用SMTP(即正在通话isSMTP()),您可以使用该SMTPDebug媒体资源获取SMTP会话的详细记录。设置如下:

1:仅显示客户端 - >服务器消息。不要使用 - 这是不太可能告诉你任何有用的。
2:显示客户端 - >服务器和服务器 - >客户端消息 - 这通常是您想要的设置
3:As 2,还显示有关初始连接的详细信息; 只有在连接出现问题时才使用(例如连接超时)
4:as 3,还显示详细的低级流量。只有真正有用的分析协议级的错误,非常详细,可能不是你需要的。
通过在脚本中包括这样的行来设置此选项:

$mail->SMTPDebug = 2;
输出格式将自适应命令行或HTML输出,但您可以使用Debugoutput属性覆盖此。

“SMTP错误:无法连接到SMTP主机。

这也可能显示为SMTP connect() failed或Called Mail() without being connected在调试输出中。这通常被报告为PHPMailer问题,但它几乎总是下降到本地DNS故障,防火墙阻止(例如GoDaddy)或本地网络上的其他问题。这意味着PHPMailer无法联系您在Host属性中指定的SMTP服务器,但没有说明为什么。它也可能由未openssl加载扩展名引起(请参阅下面的加密注释)。

下面讨论一些诊断此错误的来源的技术。

去吧爸爸

受欢迎的美国托管服务提供商GoDaddy对发送电子邮件施加了非常严格的限制(到几乎无用的点)。它们阻止到端口25,465和587的出站SMTP到除自己以外的所有服务器。这个问题是Stack Overflow上的许多令人沮丧的问题的主题。如果你发现你的脚本在你的本地机器上工作,但不是当你上传到GoDaddy,这将是你发生了什么。GoDaddy的解决方案是非常糟糕的文档:你必须通过他们的服务器,并禁用所有的安全功能,用户名和密码(伟大的,嗯?!),给你这个配置PHPMailer:

$ mail - > isSMTP();
$ mail - > Host  =  ' relay-hosting.secureserver.net ' ;
$ mail - > Port  =  25 ;
$ mail - > SMTPAuth  =  false ;
$ mail - > SMTPSecure  =  false ;
GoDaddy也拒绝发送一个From属于任何aol,gmail,yahoo,hotmail,live,aim或msn域的地址(见他们的文档)。这是因为所有这些域都部署了SPF和DKIM防伪措施,并且伪造您的地址是伪造的。

您可能会发现更容易切换到更开明的托管提供商。

阅读SMTP脚本

如果您设置SMTPDebug = 2或更高,您将看到远程SMTP服务器说明什么。通常,这会告诉你确切的错误 - 例如“密码不正确”,有时是一个页面的URL,以帮助您诊断问题。阅读它说的。Google做了这么多 - 有关“允许安全性较低的应用”设置的信息,请参见下文。

DNS失败

这些通常被视为连接超时,或“临时故障名称解析”,“无法解析主机”,“getaddrinfo失败”或类似错误。通过使用该dig工具(从dnsutilsDebian / Ubuntu上的软件包)检查您的DNS是否正在工作:

dig + short smtp.gmail.com
如果你的DNS工作,你会得到这样的东西:

gmail-smtp-msa.l.google.com。
173.194.67.108
173.194.67.109
如果这失败,PHPMailer将无法发送电子邮件,因为它将无法获取正确的IP地址连接到。如果您在DNS中没有名称,则可以直接使用IP地址作为主机名。要解决这个问题,你需要找出你的DNS为什么不工作 - 也许你还没有设置你的解析器?

检查它在那里

即使是所有服务被禁用的服务器通常会响应简单的ping,所以如果你知道你的DNS是确定的,请检查服务器是否真的存在:

ping smtp.gmail.com
你应该看到这样的东西(按ctrl-C停止它):

PING gmail-smtp-msa.l.google.com (74.125.133.108): 56 data bytes
64 bytes from 74.125.133.108: icmp_seq=0 ttl=43 time=72.636 ms
64 bytes from 74.125.133.108: icmp_seq=1 ttl=43 time=68.841 ms
64 bytes from 74.125.133.108: icmp_seq=2 ttl=43 time=68.500 ms
检查它是一个邮件服务器

这可能是一些其他服务正在尝试连接到的SMTP端口上运行。您可以使用此telnet工具(例如,在提交服务端口上连接到gmail)进行检查:

telnet smtp.gmail.com 587
这应该给你这样的:

Trying 173.194.67.109...
Connected to gmail-smtp-msa.l.google.com.
Escape character is '^]'.
220 mx.google.com ESMTP ex2sm16805587wjd.30 - gsmtp
(输入quit以退出)。如果端口587不工作,您可以尝试端口465或端口25,并使用任何一个工作 - 但要记住,端口25通常不支持加密(请参阅加密说明)。

如果它没有产生输出或没有开始的东西220,那么你的服务器关闭或你有错误的服务器。

防火墙重定向

另一件值得注意的事情是,邮件服务器响应的名称应该与您请求的服务器相关,您可以在上面的示例中看到 - 我们要求smtp.gmail.com并得到gmail-smtp-msa.l.google.com,这看起来像是与google有关 -如果您看到的是ISP的名称,那么这可能意味着您的ISP的防火墙将您透明地重定向到自己的邮件服务器,您可能会看到身份验证失败,因为您登录到错误的服务器。这很可能发生在端口25,但不太可能发生在端口465和587,所以这是另一个使用加密的原因!

SELinux阻塞

如果您看到类似的错误SMTP -> ERROR: Failed to connect to server: Permission denied (13),您可能正在运行SELinux,防止PHP或Web服务器发送电子邮件。这在RedHat / Fedora / Centos上尤其可能。使用该getsebool命令,我们可以检查是否允许httpd守护程序通过网络进行连接并发送电子邮件:

getsebool httpd_can_sendmail
getsebool httpd_can_network_connect
此命令将返回布尔开或关。如果它关闭,我们可以打开它:

sudo setsebool -P httpd_can_sendmail 1
sudo setsebool -P httpd_can_network_connect 1
如果你通过fastcgi运行PHP-FPM,你可能需要将它应用到fpm守护进程而不是httpd。

IPv6阻止

一些服务提供商(包括数字海洋)为服务器提供IPv6连接,但阻止IPv6上的出站SMTP,而在IPv4上允许。这可以通过显式地将Host属性设置为IPv4地址来解决(该gethostbyname功能仅执行IPv4查找):

$mail->Host = gethostbyname('smtp.gmail.com');
认证失败

如果您的身份验证失败,则可能有以下几种原因:

您的用户名或密码错误
您的连接正在转移到其他服务器(如上所述)
您指定的认证未加密
一般来说,您不想通过未加密的链接发送用户名或密码。一些SMTP认证方案确实增加了最低级别的安全性(发送短散列而不是明文),但这些仅提供最低限度的保护,因此大多数服务器不允许没有加密的认证。通过设置解决这个问题SMTPSecure = 'tls',并Port = 587以及设置Username和Password属性。

Gmail,OAuth2和“允许安全性较低的应用”

自2014年12月起,Google开始强制使用基于OAuth2的身份验证机制XOAUTH2,以访问其应用(包括Gmail)。此更改可能会阻止SMTP和IMAP对gmail的访问,您可能会收到来自许多电子邮件客户端(包括PHPMailer,Apple Mail,Outlook,Thunderbird和其他)的身份验证失败(通常是“5.7.14请通过Web浏览器登录”)。错误输出可能包含指向https://support.google.com/mail/bin/answer.py?answer=78754的链接,其中列出了可能的补救措施。在PHPMailer中有两个主要的解决方案:

启用“ 允许较少安全的应用程序 ”通常会解决PHPMailer的问题,它不会真正让你的应用程序显着降低安全性。据报告,更改此设置可能需要一小时或更长时间才能生效,因此不要期望立即修复。
PHPMailer在版本5.2.11中添加了对XOAUTH2的支持,但是您必须运行PHP 5.5或更高版本才能使用它。关于如何设置它的文档可以在这个wiki页面上找到。
使用加密

毫无疑问,你应该在每一个机会使用加密,否则你会邀请各种不愉快的可能性,钓鱼,身份盗窃等。

要使用任何类型的加密,您需要启用opensslPHP扩展。如果你没有安装它,或者配置不正确,你可能在连接STARTTLS阶段有麻烦。通过查看phpinfo()或php -i(查找“openssl”部分)openssl的输出php -m,或者在输出中列出来检查这一点,或者运行这行代码:

<?php  echo(extension_loaded(' openssl ')?' SSL loaded ':' SSL not loaded ')。“ \ n ” ; ?>
至于使用什么样的类型,答案一般很简单:不要在端口465上使用SSL,它自1998年以来被弃用,并且仅由未获得备忘录的Microsoft产品使用; 请使用端口587上的TLS:

$ mail - > SMTPSecure  =  ' tls ' ;
$ mail - > Host  =  ' smtp.gmail.com ' ;
$ mail - > Port  =  587 ;
或更简洁:

$ mail - > Host  =  ' tls://smtp.gmail.com:587 ' ;
不要混淆这些模式; 有效组合tls在端口587(或可能25)上和ssl在端口465 ssl上。在端口587上或tls在端口465 上将不工作。

机会性TLS

PHPMailer 5.2.10引入机会主义TLS - 如果它看到服务器正在发布TLS加密(连接到服务器之后),它会自动启用加密,即使您尚未设置SMTPSecure。这可能如果服务器是广告与TLS证书无效造成的问题,但你可以将其关闭$mail->SMTPAutoTLS = false;。

PHP 5.6证书验证失败

在与早期版本的更改中,PHP 5.6验证SSL连接上的证书。如果您要连接的服务器的SSL配置不正确,您将收到如下错误:

Warning: stream_socket_enable_crypto(): SSL operation failed with code 1.
OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
正确的解决方法是用无效的,错误配置的或自签名的证书替换。如果没有,你可以通过PHPMailer 5.2.10中引入的属性允许不安全的连接SMTPOptions(可以通过在早期版本中对SMTP类进行子类化来实现),但不建议这样做:

$邮件- > SMTPOptions  =  阵列(
' SSL ' => 阵列(' verify_peer ' => 假,' verify_peer_name ' => 假,' allow_self_signed ' => 真     ));      
          
          
          

你也可以在php.ini中全局更改这些设置,但这是一个很糟糕的主意; PHP 5.6做出这个改变有很好的理由。

有时这种行为不是那么明显; 有时加密失败可能会出现为客户端QUIT在尝试执行后立即发出STARTTLS。如果发生这种情况,您应该检查您的证书或验证设置的状态。

cURL错误60

您可能会看到错误cURL error 60: SSL certificate problem: unable to get local issuer certificate。这可能是因为您的CA文件已过期或缺失。您可以从curl下载最新的CA证书文件,将其安装在可访问的地方,并从您的php.ini文件中指向它openssl.cafile和curl.cainfo属性。

这个错误也可能导致如果你的PHP使用libcurl编译libressl(homebrew上的一个常见选项),它有一个与此相关的错误,而不是默认openssl或OS X的内置安全传输 - 运行curl -V会告诉你,你的是编译的,像这样:

curl 7.48.0 (x86_64-apple-darwin15.4.0) libcurl/7.48.0 OpenSSL/1.0.2g zlib/1.2.5 libssh2/1.7.0 nghttp2/1.9.2
标准OS X安装将使用安全传输:

curl 7.43.0 (x86_64-apple-darwin15.0) libcurl/7.43.0 SecureTransport zlib/1.2.5
在PHP外测试SSL

为了消除PHP配置或您的代码加密问题,您可以使用本地openssl安装直接使用其内置的SMTP客户端测试配置,例如:

openssl s_client -starttls smtp -crlf -connect smtp.gmail.com:587
你应该得到这样的响应:

CONNECTED(00000003)
depth=2 /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=smtp.gmail.com
   i:/C=US/O=Google Inc/CN=Google Internet Authority G2
 1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIEgDCCA2igAwIBAgIIQKPDG0sroxQwDQYJKoZIhvcNAQELBQAwSTELMAkGA1UE
BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl
cm5ldCBBdXRob3JpdHkgRzIwHhcNMTYwNDA3MDkwMzU5WhcNMTYwNjMwMDgyMDAw
WjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN
TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UEAwwOc210
cC5nbWFpbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNsHDL
zDdAFIunNFHuvBgE3ri8CinYqrPwh8LPhxNo7gnIxSOIASzlBa1xm4uBpInsWJLK
RxcqjQfGRRki558+ed5L2TrX3uoznEGAsoptatSPDuDaSttHjKX6ZOjbBEAxHp4r
ozplRFucGma7WkF1XR7htjdofWFCVN/u++Bhp1vJwO9RY2iwywjIVGqY4V9hYGHo
O0PKJSHTkIPHKZS1hSuM5f2P197cKrQVrFYx2dDMowJlCq8eEf1sp+38UXQEfqjo
BYNAj29ihiwmvYC/bN+6gZcn+vsR2w77p8tkLLzqY/vZ67Una6Qa+eV4Bl5Kmwwk
D1C1MDdoHTI8HDl9AgMBAAGjggFLMIIBRzAdBgNVHSUEFjAUBggrBgEFBQcDAQYI
KwYBBQUHAwIwGQYDVR0RBBIwEIIOc210cC5nbWFpbC5jb20waAYIKwYBBQUHAQEE
XDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3J0
MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9vY3NwMB0G
A1UdDgQWBBSEsJM0ANFUgqu5Qc3/VU+gllUUOjAMBgNVHRMBAf8EAjAAMB8GA1Ud
IwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMCEGA1UdIAQaMBgwDAYKKwYBBAHW
eQIFATAIBgZngQwBAgIwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL3BraS5nb29n
bGUuY29tL0dJQUcyLmNybDANBgkqhkiG9w0BAQsFAAOCAQEAhttyyIAjATMjXG03
kLgoKwHAZQ4ViSe2pt/DEMDUJNXBfJ+v6SI9wBE3QRHz6P/m5LkwoBeOrSiaNsiW
CrSZiBGFAj6/OBUUciHIPc/dKMYRFZ61wPArXD0VFJBtCV7cBSVvU3aW0YMPoufR
8UtjlOaTnm7pLqViGRy65EUwztznVe7eIi91X3pKPjg+TkoJmsbRes1ySmeQ06LV
1cWGd2HMOapOHK+cyQP2Uuo4ZAo5Hgiy9nnDRMmvShT2dKbIv19JyrfXPguZ/E7I
6z/Z/Fi7ilSrrpx/Frd8XwRCNQJPWfd2cV6NqGLwNR2qSCA0gJaWdIvJYqITw0lL
cAh6QQ==
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=smtp.gmail.com
issuer=/C=US/O=Google Inc/CN=Google Internet Authority G2
---
No client certificate CA names sent
---
SSL handshake has read 3494 bytes and written 491 bytes
---
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES128-SHA
    Session-ID: 936F1A0663F5CE73943C00650C2FB2B9612E1F9819D38A7CD853DB9130D0E5EE
    Session-ID-ctx:
    Master-Key: C092C10C71219E0BE8358CD432120D94CA39B01EDDA8A7007B08D7E86A74B6A16B14345610255063E1B0A2DB55D86635
    Key-Arg   : None
    Start Time: 1460541074
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
250 SMTPUTF8
(只需输入“QUIT”即可)。注意,验证返回码为0,表示验证成功。这verify error:num=20:unable to get local issuer certificate不是问题。您可以对自己的服务器或使用不同的端口进行相同类型的连接,但如果连接到端口465,则应跳过该-starttls smtp选项。

“无法实例化邮件功能”

这意味着您的PHP安装未配置为正确调用mail()函数(例如,在您的PHP中未正确sendmail_path设置php.ini),或者没有安装和配置本地邮件服务器。要解决这个问题,你需要做一个或多个这样的事情:

安装本地邮件服务器(例如后缀)。
确保你的sendmail_path点在sendmail二进制(通常/usr/sbin/sendmail)在你的php.ini。注意,在Ubuntu / Debian,你可能有多个.ini文件在/etc/php5/mods-available可能的其他位置。
使用isSendmail()并设置PHPMailer($mail->Sendmail = '/usr/sbin/sendmail';)中sendmail二进制文件的路径。
使用isSMTP()和直接使用SMTP发送。
寻址

请务必使用有效的电子邮件地址。这PHPMailer的接受的电子邮件地址属性的每一个地方,它需要一个RFC821格式的地址,不是一个RFC822之一,例如user@example.com,没有 Joe User <user@example.com>。所有接受电子邮件地址的函数,如果地址被接受,addAddress将返回一个布尔值true。包含非ascii字符的café.com域名将使用IDN'punycode'格式,在您询问PHPMailer之前无法正确评估send(),因此与它们相关的错误将会比常规地址更晚。

它仍然不工作!

如果任何上述检查失败,PHPMailer将不工作,通常没有什么PHPMailer可以做到。因此,请修复您的网络,然后重试。如果你不控制自己的防火墙或DNS,你可能需要与你的ISP提出支持票,以解决这个问题(他们很常见的阻止或转移端口25出站)。如果他们不能解决它,你需要更换你的ISP。 PS:BlueHost不支持smtp.gmail.com,他们希望您使用他们的smtp服务器。解决方法是使用与BlueHost相关联的电子邮件及其主机地址,或在这种情况下使用mail()函数发送。

在哪里可以获得帮助?

几个资源值得检查:

PHPMailer提供的代码示例。基于这些代码,而不是2003年的一些古代例子。
API文档。
代码本身 - 这是非常好的评论。
问题跟踪器 - 这很可能是一个类似于你的问题发生过的问题,所以在搜索 之前打开票。如果您确实产生了问题,请确保包含您的代码,最好是尽可能少地重现或定义问题,以便我们有机会看到您看到的内容 - 说“它不工作”不是一个错误报告!
StackOverflow - 有大量的PHPMailer问题,其中绝大多数可以通过阅读这个页面来解决!搜索您在发布问题之前看到的错误消息的问题。如果您在SO上发布问题,请确保您PHPMailer将其标记为我们将看到它,请不要在这里打开一个问题。问题跟踪器在这里是为PHPMailer中的实际错误,而不是您的服务器的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值