•我正在努力将Linux服务器迁移到Ubuntu 10.04到12.04的新服务器
•该服务器负责通过crontabs执行多个Perl模块。
•这些Perl模块严重依赖30-40 perl扩展。
•我已经安装了所有Perl扩展,并且crontabs能够成功处理,除了这些PERL扩展的较新版本导致的几个语法错误。
•我需要一些帮助来修改语法以使Perl脚本按预期进行处理。
这是我的错误消息:
2015/12/28 12:56:48 ./cms.pl 88 FATAL main - Can't call method "verify" on an undefined value at pm/Emails/Core.pm line 438.
代码:
#===================================================================================================
# Send an eamil
# Args: enable_clients?, BCC Arrayref [admin1@a.com, ...], Hashref { email_address, email_subject, email_body }
#===================================================================================================
sub pm::Emails::Core::send_email {
my ($self, $enable_clients, $bcc, $email) = @_;
# die('Invalid BCC array') unless $bcc;
die('Invalid Email hashref') unless ($email && $email->{email_address} && $email->{email_subject} && $email->{email_body});
$email->{email_address} = trim $email->{email_address}; # Trim the email address just to be sure no invalid emails sneak in
my $mime = undef;
my $smtp = undef;
###
# Get a handle to the logger
my $logger = Log::Log4perl->get_logger();
die('Failed to create logger') unless $logger;
###
###
# Send the email using the local SMTP server
# SPAM FILTER NOTES:
# We are sending the email as inlined HTML.
# Sending the email as a multipart with HTML & PlainText is getting flagged as SPAM.
{
my $msg = join(', ',
(
'Time:' . localtime(),
'Sending Email TO: ' . $email->{email_address},
#'BCC: ' . join(',', @$bcc),
'SUBJECT: ' . $email->{email_subject},
'Clients Enabled: ' . ($enable_clients ? 'true' : 'false')
)
);
$logger->warn($msg);
open(FILE, '>>/var/log/mail.log') or die('Failed to open mail log: /var/log/mail.log');
print FILE $msg . "\n";
close FILE;
}
###
if (!defined($self->{_phpversion_})) {
$self->{_phpversion_} = `php -r 'print phpversion();' 2>/dev/null`;
}
###
# Generate the MIME email message
$mime = MIME::Lite->new(
Subject => $email->{email_subject},
To => $email->{email_address},
Type => 'text/html',
Data => $email->{email_body},
'Reply-To' => 'test@test.com',
'Return-Path' => 'test@test.com',
From => 'test@test.com',
Organization => 'Testing',
'X-Mailer' => 'PHP' . $self->{_phpversion_}
);
###
# Check to see if we are sending the email to clients, if not then redirect to another account & update the subject
if ($enable_clients) {
$logger->warn('Sending email to clients is enabled!');
} else {
use Sys::Hostname;
$logger->warn('Sending email to clients is disabled!');
$email->{email_address} = 'test@test.com';
$email->{email_subject} = '<' . hostname . ' - ADMIN ONLY EMAIL> ' . $email->{email_subject};
$mime->replace(Subject => $email->{email_subject});
}
$mime->preamble('');
$mime->top_level(1);
$mime = $mime->as_string();
###
###
# Connect to the SMTP server & send the message
$logger->debug('Connecting to SMPT server');
$smtp = Net::SMTP->new('localhost', Timeout => 60, Debug => 0, Hello => 'test.com');
$logger->debug('Connected to SMPT server');
###
###
# Verify we can send the email to the included addresses
foreach my $email_address (($email->{email_address}), @$bcc) {
$logger->debug('Verifying Email address: ' . $email_address);
next if $smtp->verify($email_address);
$logger->warn('Failed to verify email address: ' . $email_address . ', re-connecting to SMPT');
$smtp = Net::SMTP->new('localhost', Timeout => 60, Debug => 1, Hello => 'test.com');
die('Failed to reconnect to SMPT server') unless $smtp;
last;
}
###
###
# Send the email message
$smtp->mail('test@test.com');
$smtp->bcc(@$bcc, { Notify => ['FAILURE','DELAY', 'SUCCESS'] });
$smtp->to($email->{email_address}, { Notify => ['FAILURE','DELAY', 'SUCCESS'] });
$smtp->data; # This will start the data connection for the message body
$smtp->datasend( $mime ); # This will send the data for the message body
$smtp->dataend; # This will end the message body and send the message to the user
$smtp->quit;
###
use List::Util qw[min];
sleep(min(1, int(rand(2))));
}
非常感谢任何帮助。
答案 0 :(得分:2)
在尝试调用$smtp
方法之后,您不会创建$smtp = Net::SMTP->new(...)
对象(使用verify()
)直到三行。所以当然它在这一点上是不确定的。
这种方法可行的唯一方法是,如果$smtp
也是在您未向我们展示的代码中创建的。但假设您向我们展示了$smtp
的所有提及,那么此代码可能只能在旧服务器上运行。这不是由更新版本的Perl引起的问题,它是一个永远不会起作用的逻辑错误。
解决此问题的显而易见的方法是重新排序代码,以便在尝试使用之前创建对象。但由于我只能看到少量的代码,我无法知道这是否会在其他地方产生连锁反应。
您是否考虑过付Perl程序员来帮助您进行这些迁移?期待StackOverflow的免费咨询并不是一个真正可持续的商业模式: - /
更新好的,现在您已经添加了更多代码,我们可以看到$smtp
在调用verify
之前初始化了几行。那么你为什么会收到错误?
如果您在描述new()
方法的部分中阅读documentation for Net::SMTP,则会说:
失败时会
undef
返回,$@
将包含原因 失败。
看起来这就是正在发生的事情。但是你的代码并没有检查来自new()
的返回代码,并假设它总能工作 - 这是一个非常奇怪的假设。要弄清楚出了什么问题,您需要在创建SMTP对象的两行中添加一些调试输出。你在哪里:
$smtp = Net::SMTP->new(...);
将其更改为:
$smtp = Net::SMTP->new(...)
or die $@;
这样,如果您无法连接到SMTP服务器,您的程序将会死于(希望)有用的错误消息,这将使您能够进一步调查。
顺便说一句,我不知道你的代码来自哪里,但是现在没有人真正推荐Net :: SMTP。这一切都相当低级。你最好看Email::Sender或Email::Stuffer(这是Perl程序员为这个项目带来的有用知识......
答案 1 :(得分:-1)
Hey Guys只是想跟进这个问题。我尝试了你所有的建议而无法得到解决方案。
然而,对这台机器上运行的SMTP / Mail的更深入研究表明,它运行的是Postfix,事实证明这个脚本是为SendMail编写的。只需执行以下操作:
卸载Postfix -
sudo apt-get purge postfix
安装Sendmail -
sudo apt-get install sendmail
一切都解决了,谢谢你们的帮助。