Net :: SMTP无法在Windows 8上连接

我写了一个微小的脚本来testing与SMTP Net::SMTP连接:

 #!/usr/bin/perl -w use strict; use Net::SMTP; my $smtp = Net::SMTP->new( 'mypc', Port => 10025, Timeout => 30, Debug => 1 ); die "Couldn't connect to SMTP server" unless $smtp; 

SMTP服务器正在mypc:10025上运行,并转储它所做的所有I / O。 当我从Debian Linux机器(64位,Perl v5.20.2)执行脚本时,SMTP服务器显示I / O活动,并且所有事情都按预期工作:

 zb226@debian8:~$ ./net_smtp.pl Net::SMTP>>> Net::SMTP(2.33) Net::SMTP>>> Net::Cmd(2.30) Net::SMTP>>> Exporter(5.71) Net::SMTP>>> IO::Socket::INET(1.35) Net::SMTP>>> IO::Socket(1.38) Net::SMTP>>> IO::Handle(1.35) Net::SMTP=GLOB(0x118adc0)<<< 220 Hi Net::SMTP=GLOB(0x118adc0)>>> EHLO localhost.localdomain Net::SMTP=GLOB(0x118adc0)<<< 250 OK 

当我在Windows 8机器(64bit,Strawberry Perl 5.22.0)上执行此操作时,没有build立连接。 我可以通过在SMTP服务器中完全没有I / O来看到这一点。 Net::SMTP不连接。 脚本刚刚死亡,正如在这种情况下预期的那样:

 C:\test>perl -w net_smtp.pl Couldn't connect to SMTP server at net_smtp.pl line 5. 

观察:

  • 有趣的是,脚本在感觉像3秒,而不是我指定的30秒之后死亡。
  • 我可以使用telnet.exe连接到SMTP服务器,它显示I / O活动。
  • 我试图完全closuresWindows防火墙没有任何改进。
  • 我有一个pipe理员暂时禁用企业防病毒软件没有任何改善。
  • 更新草莓Perl到目前推荐的5.24.0.1也没有帮助。

我不知道接下来要做什么。

编辑:尝试了一个小IO::Socket::INET脚本来validationperl实际上可以连接在这台Windows PC上:

 #!/usr/bin/perl use strict; use IO::Socket::INET; my @hosts = qw/ mypc:10025 /; foreach my $host ( @hosts ) { my $open = defined IO::Socket::INET->new(PeerAddr => $host, Timeout => 5) || 0; printf "Probed %s -> %s \n", $host, $open ? 'ok' : 'NOK'; } 

我看到SMTP服务器中的I / O,它按预期工作:

 C:\test>perl -w io_socket.pl Probed mypc:10025 -> ok 

基于来自其他答案的信息,根本的问题是,那

  • 所使用的主机名解析为IPv4和IPv6地址,
  • SMTP服务器只在IPv4地址处进行监听,或者IPv6地址被防火墙阻止,
  • 最近版本的Net :: SMTP正在使用,与旧版本相反,透明地支持IPv6和IPv4。

因为如果IPv6支持和针对IPv4 Net :: SMTP的较新IPv6的常用偏好将解析主机名,然后尝试IPv6地址并且无法连接。 直接使用IO :: Socket :: INET是可行的,因为它只是在执行IPv4(与Net :: SMTP使用的IO :: Socket :: IP相反)。

它在Linux上而不是在Windows上的原因可能是Perl的不同版本:内置IPv6(和SSL)支持的Net :: SMTP的新版本仅在Perl 5.22作为CORE模块(即Perl上的Windows(5.22)具有支持IPv6的版本,而Linux(5.20)上的Perl则不支持。

有几种方法可以解决这个问题:

  • 直接使用IPv4地址而不是主机名
  • 使SMTP服务器侦听IPv4和IPv6
  • 或指定要使用的地址族,即
    my $smtp = Net::SMTP->new( 'mypc', ..., Domain => AF_INET );

经过这个讨论 ,我发现问题与IPv6有关。 打开C:\strawberry\perl\lib\Net\SMTP.pm并更改行…

 our @ISA = ('Net::Cmd', $inet6_class || 'IO::Socket::INET'); 

…至…

 our @ISA = ('Net::Cmd', 'IO::Socket::INET'); 

…使原始脚本运行:

 C:\test>perl -w net_smtp.pl Net::SMTP>>> Net::SMTP(3.08) Net::SMTP>>> Net::Cmd(3.08) Net::SMTP>>> Exporter(5.72) Net::SMTP>>> IO::Socket::INET(1.35) Net::SMTP>>> IO::Socket(1.38) Net::SMTP>>> IO::Handle(1.36) Net::SMTP=GLOB(0x58e8fc)<<< 220 Hi Net::SMTP=GLOB(0x58e8fc)>>> EHLO localhost.localdomain Net::SMTP=GLOB(0x58e8fc)<<< 250 OK 

现在,我放心了,因为我可以继续工作,但如果有人有进一步的线索来避免这个丑陋的补丁,我会高兴地接受一个详尽的答案。

编辑:相应地,如果不进行修补, 禁用IPv6也会有效。