生产环境下SMTP配置无法工作

22
我试图在提交表单时发送电子邮件。我正在使用以下配置使用PHPMailer发送邮件。
$mail = new PHPMailer;
$mail->isSMTP();
$mail->Host = 'mail.example.in'; 
$mail->Port = 25; 
$mail->SMTPAuth = true;
$mail->Username = 'user@example.in'; 
$mail->Password = 'password'; 

$mail->setFrom("user@example.in" , "User");
$mail->addAddress('receiver@example.in', 'Receiver');
$mail->addBCC('anotheruser@somedomain.com', 'Another user');
$mail->AddReplyTo('user@example.in', 'User');

$mail->isHTML(true);

$mail->Subject = $subject;
$mail->Body    = $message;
if($mail->send())
    echo "Your request has been received. We will soon contact you.";
else echo "Unable to send your request. Please try again";
在本地主机上运行正常。但是,当我将其部署到我的服务器(example.in)时,会出现以下异常。
SMTP ERROR: Failed to connect to server: Connection timed out (110)
SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting

--编辑--

我尝试使用telnet命令连接SMTP服务器,但无法添加收件人。我收到了以下错误消息?

Last login: Fri Sep 16 11:08:06 on ttys000
admin:~ admin$ telnet mail.example.in 25
Trying 111.91.153.112...
Connected to mail.example.in.
Escape character is '^]'.
220 fbs-ho-mailserver.example.in ESMTP Service (Lotus Domino Release 8.5.3FP3) ready at Fri, 16 Sep 2016 11:36:01 +0530
HELO example.in
250 fbs-ho-mailserver.example.in Hello example.in ([111.91.127.222]), pleased to meet you
MAIL from: marketing@example.in
250 marketing@example.in... Sender OK
RCPT to: john.hh@gmail.com
554 Relay rejected for policy reasons.

-- 编辑 --

我已经在Outlook中设置了这个帐户。我真的很困惑发生了什么。

输入图像描述


听起来像是您的生产环境阻止了对电子邮件服务器的出站连接,或者是邮件服务器阻止了入站连接。请与运维人员沟通解决。 - Joni
我认为mail.example.in不是一个有效的SMTP服务器。 - user5189304
我添加了mail.example.in,因为我不想透露实际的SMTP服务器名称。 - Aakash
不,我是从我的本地机器上测试的。PHPMailer正在HostGator上运行,我不确定如何在那里进行测试。 - Aakash
我正在检查答案。我需要与某人合作来验证它。 - Aakash
显示剩余10条评论
12个回答

5

您的错误提示如下:

SMTP ERROR: Failed to connect to server: Connection timed out (110)
SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting

因此,让我们看一下https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting

"SMTP Error: Could not connect to SMTP host."

This may also appear as SMTP connect() failed or Called Mail() without being connected in debug output. This is often reported as a PHPMailer problem, but it's almost always down to local DNS failure, firewall blocking (for example as GoDaddy does) or other issue on your local network. It means that PHPMailer is unable to contact the SMTP server you have specified in the Host property, but doesn't say exactly why. It can also be caused by not having the openssl extension loaded (See encryption notes below).

Some techniques to diagnose the source of this error are discussed below.

GoDaddy

Popular US hosting provider GoDaddy imposes very strict (to the point of becoming almost useless) constraints on sending email. They block outbound SMTP to ports 25, 465 and 587 to all servers except their own. This problem is the subject of many frustrating questions on Stack Overflow. If you find your script works on your local machine, but not when you upload it to GoDaddy, this will be what's happening to you. The solution is extremely poorly documented by GoDaddy: you must send through their servers, and also disable all security features, username and password (great, huh?!), giving you this config for PHPMailer:

$mail->isSMTP();
$mail->Host = 'relay-hosting.secureserver.net';
$mail->Port = 25;
$mail->SMTPAuth = false;
$mail->SMTPSecure = false;

GoDaddy also refuses to send with a From address belonging to any aol, gmail, yahoo, hotmail, live, aim, or msn domain (see their docs). This is because all those domains deploy SPF and DKIM anti-forgery measures, and faking your from address is forgery.

You may find it easier to switch to a more enlightened hosting provider.


2
你遇到的问题 - 实际上是两个不相关的问题 - 很简单:
SMTP错误:无法连接服务器:连接超时(110)SMTP connect() 失败。
而你已经验证了服务器确实可以接受连接:
我尝试使用telnet命令连接SMTP服务器。
Last login: Fri Sep 16 11:08:06 on ttys000
admin:~ admin$ telnet mail.example.in 25
Trying 111.91.153.112...
Connected to mail.example.in.

当从生产服务器运行时,你的脚本无法连接到SMTP服务器。可能的原因是生产服务器有防火墙,为了避免滥用,阻止了任何对外部的连接。该服务器可以提供Web请求,但不能做更多。

如果你的测试已经验证了端口25没有响应,那么(在确认主机地址正确后),你可以尝试使用telnet mail.example.in 587。如果这个方法起作用了,就意味着服务器不接受不安全的连接(端口25),但接受安全连接。使用PHPMailer,你可以尝试激活安全连接

$mail->SMTPSecure = 'tls';

或者

$mail->SMTPSecure = 'ssl';

如果这不起作用,您可能仍然有防火墙问题;或者您需要查看phpinfo()并验证您是否在PHP中有可用的OpenSSL支持。
你需要做的事情:
要求维护生产服务器的IT人员打开防火墙; 更有前途的是,询问他们如何从该服务器发送电子邮件。很可能您需要使用mail()函数,或者使用localhost127.0.0.1作为SMTP服务器。然后,电子邮件将通过您的生产服务器服务网络发送出去。 他们可能会告诉您不允许使用25号端口,但可能允许使用(比如)465或567端口。您将不得不相应地更新配置和/或添加TLS / SSL(请参见上文)。
或者,您可能被允许连接到第三方SMTP服务器,您需要提供IP地址以允许IT人员打开适当的防火墙窗口。然后,电子邮件将通过第三方服务器发送。
第二个问题(可能不是问题)
250 marketing@example.in...发送者OK RCPT to:john.hh@gmail.com 554由于策略原因中继器被拒绝
另外为了避免滥用,SMTP服务器不会让每个人都连接并发送电子邮件,而只能让他们自己的客户这样做。我看到在PHPMailer配置中,您指定了一个用户和密码。在telnet会话中没有。因此,PHPmailer可能可以发送,但无法连接,而您的telnet可以连接,但无法发送。
一旦解决了连接问题,您的身份验证问题将得到解决或消失(因为您将使用IT人员提供给您的不同服务器,例如localhost)。
第三个问题(可能永远不会出现)
滥用服务的第三种方法是超额使用 - 向太多人发送太多电子邮件。与IT人员核实发送电子邮件的可接受政策。
问题,问题
需要查看源的可信度(您可能希望代表某些未指定您选择的SMTP服务器为允许发件人的域发送电子邮件),以及数据的机密性(即使使用TLS / SSL连接,如果您被赋予localhost作为SMTP服务器,则您的IT人员将完全,不受限制,无法检测地访问发送的任何电子邮件。这可能或可能不适合您)。

1
我认为只需几个步骤,我们就可以使其正常工作。
1. 在您的Godaddy/Hostgator Cpanel中,选择MX记录 > 选择相关域名 > 选择“远程邮件交换器”。 您可以在此时测试邮件传递,问题可能已经解决。
2. 我确定设置正确,但是当涉及到Cpanel、PhpMailer和Godaddy/Hostgator时,请相信我。这是一个常识毫无意义的地方。
请将以下内容替换:
$mail->Host = 'mail.example.in';

with:

$mail->Host = 'localhost';

我相信只要登录凭据有效,这应该解决任何问题。

1

第一引用(来自ibm社区):

john.hh@gmail.com是Reject组的成员,该组列在gmail.com的“拒绝发送至以下互联网地址的邮件”字段中(目标服务器的Domino配置文档的路由器/SMTP、限制和控制、SMTP入站控制选项卡的“入站预期收件人控制”部分)。

从Reject(组)文档的成员列表中删除Mary的分层名称(Mary Jones/ABC)允许Mary从互联网接收邮件。

第二引用:

大多数邮件服务器为防止它们被用作匿名垃圾邮件中继而配置仅从某些主机中中继邮件。


1
使用自己的SMTP是个坏主意。根据你处理邮件的方式,有很大的机会让你的邮件在某些方面被阻止或标记为垃圾邮件。而且你将不得不花费一些时间来保持你的服务器最新。

使用在线服务,这些服务对每个提供商都是白名单,并公开API以发送您的事务邮件: https://www.mailjet.com/ http://mailchimp.com/ ...

他们通常为小数量(每日低于2000封电子邮件)提供免费帐户。使用API非常简单,并且可以在几分钟内完成(例如:https://dev.mailjet.com/)。


1

如果您的服务器上启用了smtp,请向您的托管提供商询问。我之前遇到过smtp和curl都有问题的情况。请联系托管提供商。


SMTP已启用。我能够使用PHP的邮件功能发送电子邮件。但是,我的要求是按照问题中所述的配置来使用。 - Aakash
尝试在其他操作之前添加此行代码 $mail->IsSMTP(),或者可能是一些端口问题。 - Akash Ganatra
我已经添加了这行代码。我也更新了问题。 - Aakash

1

phpmailer的版本是多少?

你可能忘记添加这行代码

  $mail->IsSMTP(); //  use SMTP

在你启动 $mail 后。

试一试。


我正在使用PHPMailer 5.2.14版本。另外,我已经更新了问题。 - Aakash

1

我遇到了类似的超时问题,原因是我的主机提供商(Linode)。 简而言之,自2019年11月5日后创建的Linode账户默认设置了SMTP限制。您需要为您的实例配置rDNS,并打开支持票证明符合CAN-SPAM条款,支持应该很快解除限制。我想很多人都会因为smtp限制而面临这个问题。


1
所以你有一个GoDaddy服务器,想要通过新获得的SMTP Relay发送电子邮件。如果你在Google上搜索一下,你可能会发现“你不能这样做”。

如果你再搜索一下,你可能会发现GoDaddy的官方解决方案是使用他们内部的邮件中继。这并不理想,因为他们设置了任意的障碍,比如这个:

我们的专用服务器每天的出站邮件限制为1000封。如果您需要发送超过1000封电子邮件,请致电客户支持或打开支持工单以请求更高的限制。

快速有效的解决方案:获取支持使用HTTP API发送电子邮件的SMTP Relay。

我的建议:(一个简单而有效的工作方案,我个人正在使用)

Sendgrid注册一个帐户。 Sendgrid每月提供免费12k封电子邮件,我认为这应该足够满足任何基本需求。

第一步: Sendgrid会要求你添加一些DNS记录,以验证你代表该主机发送电子邮件。所以去做吧。

第二步: 配置白标签 https://sendgrid.com/docs/User_Guide/Settings/Whitelabel/index.html (这不是必要的,但它会使您发送的电子邮件看起来更专业)

第三步: 生成 API 密钥

您可以从 SendGrid 客户门户 管理您的 API 密钥。此外,您还可以通过 API 自身管理您的 API 密钥

第四步: 开始编写我们的代码。

使用在 Github 上可用的,使用 PHP 在 sendgrid 上发送邮件很容易。

// using SendGrid's PHP Library
// https://github.com/sendgrid/sendgrid-php
require 'vendor/autoload.php';
$sendgrid = new SendGrid("SENDGRID_APIKEY");
$email    = new SendGrid\Email();

$email->addTo("test@sendgrid.com")
      ->setFrom("you@youremail.com")
      ->setSubject("Sending with SendGrid is Fun")
      ->setHtml("and easy to do anywhere, even with PHP");

$sendgrid->send($email);

工作原理

GoDaddy阻止25、2525、587和485端口,这些端口是SMTP的理想端口。因此,我们使用80/443端口,并请求sengrid的API使用80端口代表我们发送电子邮件,是的,我们愚弄了GoDaddy。


这可能是许多人正在寻找的魔法,所以我会点赞这个答案。然而,要小心相信你已经“愚弄”了你的ISP。流量监控很容易,如果ISP决定阻止发送到SendGrid服务器的出站流量,他们可以立即做到。如果可能的话,始终尝试与您的ISP合作 - 或更改ISP; 尽量避免欺骗您的连接提供商。 - LSerni
@lserni 是的!但在许多情况下,我们可以覆盖发送到 Sendgrid 的 80 端口的阻止,例如使用反弹或 VPN。无论如何,这是我目前正在使用的工作解决方案。Godaddy 永远不会删除这些限制,我尝试了很长时间。 - Sibidharan
@lserni OP 正在使用 GoDaddy。查找此评论“我能够使用 Gmail 和 GoDaddy 的 SMTP 配置发送邮件。只有这个使用 25 号端口的特定配置不起作用。” 以回答作者的问题。 - Sibidharan
1
是的,评论已经“折叠”了,所以我再也看不见它了 :-)。我的意思是,在操作者的情况下,也许只使用 mail() 是最快的解决方案。对于似乎是一个简单的联系表格而言, PHPMailer 有些过度设计。 - LSerni
是的,那确实是正确的。但这个解决方案,有很多人正在寻找它。 - Sibidharan
显示剩余2条评论

0

超时错误通常是数据包丢失的典型表现,这可能是 Web 服务器和 SMTP 服务器之间防火墙问题所致。 如果您可以访问服务器的 ssh,可以尝试使用以下命令连接到 smtp:

telnet <smtp server> 25

即使使用 telnet 仍出现超时错误,你非常确定问题在于网络/防火墙方面。


1
非常奇怪。您进行的Telnet测试是从运行PHPMailer的Web服务器执行的? - Edo
不,它不是在服务器上运行的。它是在我的本地电脑上运行的。 - Aakash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接