本文介绍了GMail 421 4.7.0请稍后再试,关闭连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正试图找出原因,为什么它无法使用GMail从我的服务器发送邮件.为此,我使用了SwiftMailer,但可以将问题包含在以下隔离的代码中:

I'am trying to find out, why it fails to send mails from my server with GMail. For this I use SwiftMailer but I can enclose the problem to the following isolated code:

<?php

$sock = stream_socket_client('tcp://smtp.gmail.com:587', $errno, $errstr);
if (false == $sock) {
    die('error');
}
$server_response = fread($sock, 4096);
echo $server_response . PHP_EOL;
fclose($sock);

当我在本地计算机(Windows 10,XAMPP,PHP 5.6.24)上运行此代码时,输​​出为:

When I run this code on my local machine (Windows 10, XAMPP, PHP 5.6.24), the output is:


220 smtp.gmail.com ESMTP qp16sm1358626ejb.89 - gsmtp

所以220表示一切都很好.

So 220 means everything is fine.

但是当我在服务器上运行完全相同的代码(Debian Jessie,PHP 5.6.38)时,输出为:

But when I run the exact same code on my server (Debian Jessie, PHP 5.6.38), the output is:


421 4.7.0 Try again later, closing connection.

GMail的错误参考 https://support.google.com/a/answer/3726730 对此错误消息不提供任何建议.

GMail's error reference https://support.google.com/a/answer/3726730 doesn't give any advice for this error message.

我也在没有PHP的服务器控制台上尝试了这一点,它也可以正常工作:

I also tried this on the server console without PHP and it works fine too:


> nc smtp.gmail.com 587
$ 220 smtp.gmail.com ESMTP n11sm3188821wmi.15 - gsmtp

所以我可以界定问题

  • 与我的GMail帐户的任何安全设置无关(因为此时未发送身份验证)
  • 我的服务器未在GMail上列入黑名单(因为 nc 命令可以正常工作)
  • It has nothing to do with any security settings of my GMail account (because no authentification is sent at this point)
  • My server is not blacklisted on GMail (because the nc command works fine)

是否有可能导致此错误的php.ini设置?

Are there any settings of the php.ini that can cause this error?

更新

只是为了好玩,我在另一台机器的端口587上设置了一个简单的TCP服务器,并显示了所有已连接客户端的IP地址.如果使用上面的PHP客户端代码或通过 nc 命令进行连接,则没有什么不同.我不知道通过客户端PHP代码和 nc 命令进行联网时,GMail的SMTP服务器可能会有什么不同.

Just for fun I set up a simple TCP server on port 587 on another machine and display the IP address of any connected client.There is no different if I use the above PHP client code or connecting via nc command.I don't know what could be the different for the GMail's SMTP server while conneting via the client PHP code and the nc command.

更新2

nc 命令中启用详细模式时, DNS fwd/rev不匹配可能会是一个问题吗?

While enabling verbose mode in the nc command, could DNS fwd/rev mismatch be a problem?


> nc -v smtp.gmail.com 587
$ DNS fwd/rev mismatch: smtp.gmail.com != wr-in-f109.1e100.net
$ smtp.gmail.com [108.177.15.109] 587 (submission) open
$ 220 smtp.gmail.com ESMTP z15sm4348737wrn.89 - gsmtp

更新3

使用以下代码运行上面的代码

Run the above code with

$sock = stream_socket_client('tcp://wr-in-f109.1e100.net:587', $errno, $errstr);

工作正常,它的响应为220.但是问题是,SwiftMailer尝试使用 stream_socket_enable_crypto()之后建立TLS安全性,但失败

It works, it responses with 220. But the problem is, SwiftMailer try to establish TLS security after with stream_socket_enable_crypto() and this fails with


Peer certificate CN=`smtp.gmail.com' did not match expected CN=`wr-in-f109.1e100.net'

更新4

这让我发疯.当我使用Python的TCP套接字连接到smtp.gmail.com时,GMail响应为220:

It's getting me crazy. When I use Python's TCP sockets to connect to smtp.gmail.com, GMail responses with 220:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('smtp.gmail.com', 587))
data = s.recv(4096)
s.close()

print data

输出:


220 smtp.gmail.com ESMTP p6sm8392243wmg.0 - gsmtp

Python的套接字和PHP的stream_socket_client有什么区别?

What is the difference between Python's sockets and PHP's stream_socket_client?

修改:与PHP的非流套接字功能相同的行为:

Edit:The same behavior with PHP's non-streaming socket function:

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if(!is_resource($socket)) onSocketFailure("Failed to create socket");
socket_connect($socket, "smtp.gmail.com", 587)
        or onSocketFailure("Failed to connect", $socket);

$line = socket_read($socket, 1024, PHP_NORMAL_READ);

var_dump($line);
socket_close($socket);

更新5

现在,我认为这是IPv6的问题.我不是C语言的大程序员,但是我试图了解PHP的实现.

Now I think it is a problem with IPv6. I'am not a big C programmer but I tried to understand the PHP's implementation.

看看

  • xp_socket.c 函数 php_tcp_sockop_connect 使用 php_network_connect_socket_to_host
  • network.c 这是在此处实现
  • 它使用 php_network_getaddresses
  • 并且此函数使用 getaddrinfo
  • xp_socket.c the function php_tcp_sockop_connect uses php_network_connect_socket_to_host
  • network.c which is implemented here
  • It use php_network_getaddresses
  • and this function use getaddrinfo

php_network_connect_socket_to_host 迭代主机地址列表并尝试连接到该地址.如果成功,它将停止循环.

php_network_connect_socket_to_host iterates of the list of host addresses and tries to connect to it. If its success, it stops with looping.

我没有使用C进行尝试,但是我认为以下Python代码可以做到这一点:

I don't tried it out with C but I think the following Python code does the same:

import socket
print socket.getaddrinfo("smtp.gmail.com", 587)

哪些印刷品


[
 (10, 1, 6, '', ('2a00:1450:400c:c0c::6d', 587, 0, 0)),
 (10, 2, 17, '', ('2a00:1450:400c:c0c::6d', 587, 0, 0)),
 (10, 3, 0, '', ('2a00:1450:400c:c0c::6d', 587, 0, 0)),
 (2, 1, 6, '', ('108.177.15.109', 587)),
 (2, 2, 17, '', ('108.177.15.109', 587)),
 (2, 3, 0, '', ('108.177.15.109', 587))
]

(为了方便阅读,我对行进行了格式化)

(I formatted the line for better reading)

如您所见,列表顶部有三个IPv6地址,并且 php_network_connect_socket_to_host 首先尝试这些IPv6地址,然后再涉及IPv4地址.

As you can see, there are three IPv6 addresses on the top of the list and php_network_connect_socket_to_host try these IPv6 adresses first before it comes to the IPv4 addresses.

那么当我尝试直接连接到第一个IPv6地址时会发生什么?

So what happens when I try to connect directly to the first IPv6 address?

<?php

$sock = stream_socket_client('tcp://[2a00:1450:400c:c02::6c]:587', $errno, $errstr);
if (false == $sock) {
    die('error');
}
$server_response = fread($sock, 4096);
echo $server_response . PHP_EOL;
fclose($sock);

输出为:


421 4.7.0 Try again later, closing connection.

这个SO问题与此观察结果有关:

This SO question is related to this observation: Why I can't send emails using smtp.gmail.com:587 on ipv6?

推荐答案

发现后,使用IPv6地址时会出现错误消息,黑客更喜欢使用IPv4地址.

After finding out, that the error message happens when the IPv6 address is used the hack is to prefer the IPv4 address.

根据 https://serverfault.com/questions/511237/linux-block-ipv6-for-certain-applications-hostnames#answer-514397 最简单的方法是将以下行添加到 etc/hosts :

Acording to https://serverfault.com/questions/511237/linux-block-ipv6-for-certain-applications-hostnames#answer-514397 the easiest way was to put the following line to etc/hosts:

108.177.15.109 smtp.gmail.com

此解决方案的缺点是静态IP地址. smtp.gmail.com 可能会更改IP地址.这就是为什么我不将此答案标记为接受的原因.

The drawback of this solution is the static IP address. smtp.gmail.com might change the IP address. This is the cause why I don't mark this answer as accepted.

我不知道是否可以配置 /etc/gai.conf 仅将 smtp.gmail.com 首选IPv4,而不是IPv6.

I don't know if its possible to configure /etc/gai.conf to prefer IPv4 over IPv6 for only smtp.gmail.com.

本文可能会很有趣,以便详细了解getaddrinfo的工作方式: https://jameshfisher.com/2018/02/03/what-does-getaddrinfo-do/

This article might be interesting to get a detailed look, how getaddrinfo works: https://jameshfisher.com/2018/02/03/what-does-getaddrinfo-do/

这篇关于GMail 421 4.7.0请稍后再试,关闭连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-17 10:47
查看更多