无法调用方法"验证"在未定义的值上

时间:2015-12-28 20:50:31

标签: perl

•我正在努力将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))));
}

非常感谢任何帮助。

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::SenderEmail::Stuffer(这是Perl程序员为这个项目带来的有用知识......

答案 1 :(得分:-1)

Hey Guys只是想跟进这个问题。我尝试了你所有的建议而无法得到解决方案。

然而,对这台机器上运行的SMTP / Mail的更深入研究表明,它运行的是Postfix,事实证明这个脚本是为SendMail编写的。只需执行以下操作:

卸载Postfix -

   sudo apt-get purge postfix

安装Sendmail -

   sudo apt-get install sendmail

一切都解决了,谢谢你们的帮助。