我在Windows 2008服务器上使用Strawberry Perl(v5.16.3)。我添加了一些用于脚本的CPAN模块,但这似乎破坏了MIME:Lite(此框中的其他脚本使用它)。当我运行以下代码时:
use strict;
use warnings;
use v5.16;
use MIME::Lite;
my $msg = MIME::Lite->new(From => 'person@domain.com',
To => 'person@domain.com',
Subject => "testing",
Type => 'multipart/mixed');
my $dataString = "Trying to figure out why this isn't working.\r\n";
$msg->attach( Type => 'TEXT',
Data => $dataString);
$msg->send('smtp', 'mailhost.com', Debug=>1);
我收到以下错误消息:
MIME::Lite::SMTP>>> MIME::Lite::SMTP
MIME::Lite::SMTP>>> Net::SMTP(3.10)
MIME::Lite::SMTP>>> Net::Cmd(3.10)
MIME::Lite::SMTP>>> Exporter(5.67)
MIME::Lite::SMTP>>> IO::Socket::INET6(2.69)
MIME::Lite::SMTP>>> IO::Socket(1.34)
MIME::Lite::SMTP>>> IO::Handle(1.33)
MIME::Lite::SMTP: Net::Cmd::_is_closed(): unexpected EOF on command channel: at d:/strawberry/perl/site/lib/MIME/Lite.pm line 2877.
SMTP Failed to connect to mail server: Bad file descriptor.
我安装的模块,其中Email :: Simple,Email :: Sender,Email :: MIME :: CreateHTML&字符串::的Util。我相信你知道,也安装了各种依赖项。
我只是将脚本切换到Email :: Sender,但是从服务器获得了421错误(这是另一个谜)。我能够通过telnet连接到邮件服务器并获得“HELO”没有问题。
我担心Perl的安装现在全都搞砸了,但我希望你们中的一个能够对如何修复它们有所了解。
提前感谢您的帮助。
编辑:我注意到perl / lib中的Socket.pm已更新。这会导致问题吗?我将MIME :: Lite更新为最新版本(版本3.030),但没有解决问题。
编辑#2:Per,ikegami的回复,在NET :: SMTP中添加了打印语句:
sub new {
print "inside Net::SMTP::new\n";
my $self = shift;
my $type = ref($self) || $self;
my ($host, %arg);
if (@_ % 2) {
$host = shift;
%arg = @_;
}
else {
%arg = @_;
$host = delete $arg{Host};
}
print "checked for SSL.\n";
if ($arg{SSL}) {
# SSL from start
die $nossl_warn if !$ssl_class;
$arg{Port} ||= 465;
}
my $hosts = defined $host ? $host : $NetConfig{smtp_hosts};
my $obj;
$arg{Timeout} = 120 if ! defined $arg{Timeout};
print "set timeout: $arg{Timeout}. \n";
foreach my $h (@{ref($hosts) ? $hosts : [$hosts]}) {
print "host: $h, port: $arg{Port}, laddr: $arg{LocalAddr}, lport: $arg{LocalPort}, familyKey: " . ( $arg{Domain} || $arg{Family} ) . "\n";
$obj = $type->SUPER::new(
PeerAddr => ($host = $h),
PeerPort => $arg{Port} || 'smtp(25)',
LocalAddr => $arg{LocalAddr},
LocalPort => $arg{LocalPort},
$family_key => $arg{Domain} || $arg{Family},
Proto => 'tcp',
Timeout => $arg{Timeout}
)
and last;
}
print "$obj\n";
return
unless defined $obj;
print "object defined. \n";
${*$obj}{'net_smtp_arg'} = \%arg;
${*$obj}{'net_smtp_host'} = $host;
print "set net_smtp_host to $host\n";
if ($arg{SSL}) {
print "setting SSL. \n";
Net::SMTP::_SSL->start_SSL($obj,%arg)
or return;
}
$obj->autoflush(1);
print "set autoflush.\n";
$obj->debug(exists $arg{Debug} ? $arg{Debug} : undef);
print "setting debug: $arg{Debug}\n";
my $response = $obj->response();
print "object response: $response (5 == CMD_ERROR)\n";
unless ($obj->response() == CMD_OK) {
my $err = ref($obj) . ": " . $obj->code . " " . $obj->message;
$obj->close();
$@ = $err;
print "returning because response was not CMD_OK\n";
return;
} ....
这是输出:
D:\strawberry>perl D:\Perl\Src\pmTasks\emailTest.pl
inside Net::SMTP::new
checked for SSL.
set timeout: 120.
Use of uninitialized value in concatenation (.) or string at D:/strawberry/perl/lib/Net/SMTP.pm line 83, <DATA> line 100
3.
Use of uninitialized value in concatenation (.) or string at D:/strawberry/perl/lib/Net/SMTP.pm line 83, <DATA> line 100
3.
Use of uninitialized value in concatenation (.) or string at D:/strawberry/perl/lib/Net/SMTP.pm line 83, <DATA> line 100
3.
Use of uninitialized value in concatenation (.) or string at D:/strawberry/perl/lib/Net/SMTP.pm line 83, <DATA> line 100
3.
host: {correct_mailhost_here}, port: , laddr: , lport: , familyKey:
MIME::Lite::SMTP=GLOB(0x1f36fbc)
object defined.
set net_smtp_host to {correct_mailhost_here}
set autoflush.
MIME::Lite::SMTP>>> MIME::Lite::SMTP
MIME::Lite::SMTP>>> Net::SMTP(3.10)
MIME::Lite::SMTP>>> Net::Cmd(3.10)
MIME::Lite::SMTP>>> Exporter(5.67)
MIME::Lite::SMTP>>> IO::Socket::INET6(2.69)
MIME::Lite::SMTP>>> IO::Socket(1.34)
MIME::Lite::SMTP>>> IO::Handle(1.33)
setting debug: 1
MIME::Lite::SMTP: Net::Cmd::_is_closed(): unexpected EOF on command channel: at D:/strawberry/perl/site/lib/MIME/Lite.pm line 2877.
object response: 5 (5 == CMD_ERROR)
MIME::Lite::SMTP: Net::Cmd::_is_closed(): unexpected EOF on command channel: at D:/strawberry/perl/site/lib/MIME/Lite.pm line 2877.
returning because response was not CMD_OK
SMTP Failed to connect to mail server: Bad file descriptor
因此,它返回的原因似乎是$obj
的响应为CMD_ERROR
。它发送给$obj=$type->SUPER::new
的唯一参数是主机。 (这是正确的主机,但我不得不在上面将其删空)。
所以,我不确定这个叫哪个超类。它似乎从NET :: Cmd返回常量,但没有new
子例程。 IO :: Socket:INET从IO :: Socket调用new,它从IO :: Handle调用new,它似乎调用了fdopen C代码?我在这里迷失了一点。但是,感谢你的帮助到目前为止。似乎我们在这里几乎找到问题的根源。
答案 0 :(得分:1)
使用Net :: SMTP版本3.x添加了对SSL和IPv6的支持。如果安装了必要的软件包(即IO :: Socket :: IP或IO :: Socket :: INET6),它将使用getaddrinfo来解析通常在IPv4之前优先使用IPv6的名称。
如果一切设置正确,这不是问题。但在您的情况下,即使没有邮件服务器侦听IPv6地址或防火墙阻止连接,邮件服务器的主机名也会解析为IPv6和IPv4地址。因此导致连接失败,因为getaddrinfo返回应该使用IPv6,但IPv6无法访问服务器。
正确的解决方法是删除主机的IPv6记录或使其可由IPv6访问。只要不是这种情况,可以通过在Net :: SMTP中明确强制执行IPv4来解决问题:
use Socket;
Net::SMTP->new(host, Domain => AF_INET,...);