log4perl запускается из другого пакета, не запуская сообщения, отправленные по электронной почте

Я вижу поведение, которое не могу объяснить, при использовании log4perl для отправки сообщения по электронной почте.

Таким образом, следующий тестовый скрипт работает нормально, и электронное письмо отправляется без проблем:

#!/usr/bin/perl
use strict;
use warnings;
use Log::Log4perl qw(:easy);
use Log::Dispatch;

my $appender_email = Log::Log4perl::Appender->new(
    "Log::Dispatch::Email::SSMTP",
    threshold => "INFO",
    to => '[email protected]',
    subject => 'Perl script message'
);

my $email_logger = get_logger();
$email_logger->level($INFO);
$email_logger->add_appender($appender_email);

$email_logger->info('hi');

Log::Dispatch::Email::SSMTP — это модуль, который я написал для отправки электронных писем с помощью команды ssmtp.

Странности начинаются, когда точно такой же код перемещается в другой пакет в другом файле в том же каталоге, что и мой исходный скрипт. Когда я делаю это и использую этот пакет из своего исходного скрипта, электронная почта не отправляется и ошибок не возникает.

Однако, если я изменю:

Log::Dispatch::Email::SSMTP

to

Log::Log4perl::Appender::Screen

Он отлично печатает «привет» на экране, когда я запускаю свой скрипт.

Итак, если log4perl работает при отправке сообщения на экран, почему он не работает при попытке отправить электронное письмо? И почему один и тот же код запускает электронное письмо из исходного скрипта, а не из пакета? Опять же, нет никаких ошибок или каких-либо указаний на то, что что-то пошло не так. И я проверил, что мой модуль загружается операторами печати. Таким образом, код моего модуля определенно загружается, но электронное письмо все еще не срабатывает.

ОБНОВЛЕНИЕ Вот код, когда он не работает по запросу в комментариях.

maillog.pl

#!/usr/bin/perl
BEGIN { unshift @INC, "/home/steve/perl/perl-lib" }
use strict;
use warnings;
use Testy;

print 'start' . "\n";

Вот пакет Testy.pm:

package Testy;
BEGIN { unshift @INC, "/home/steve/perl/perl-lib" }
use strict;
use warnings;
use Log::Log4perl qw(:easy);
use Log::Dispatch;

print 'end' . "\n";
my $appender_email = Log::Log4perl::Appender->new(
    "Log::Dispatch::Email::SSMTP",
    #"Log::Log4perl::Appender::Screen",
    threshold => "INFO",
    to => '[email protected]',
    subject => 'Perl script message'
);

my $email_logger = get_logger();
$email_logger->level($INFO);
$email_logger->add_appender($appender_email);

$email_logger->info('hi');

1;

А вот и мой модуль SSMTP, расположенный в /home/steve/perl/perl-lib/Log/Dispatch/Email/SSMTP:

package Log::Dispatch::Email::SSMTP;

use strict;
use warnings;
use Log::Dispatch::Email;
use Data::Dumper;

use base qw( Log::Dispatch::Email );
print "hi, i'm here!\n";

sub send_email {
  my $self = shift;
  my %p = @_; 
  my $to = escape ( join ',', @{$self->{to}} );
  my $subject = $self->{subject};
  my $message = $p{message};
  $message =~ s/'/'\\''/g;
  print $to . "\n";
  print $subject . "\n";
  print $message . "\n";
  print "I'm working!";

  system("echo 'To: $to\nFrom: \'Me\' <myemail\@gmail.com>\nSubject:$subject\n\n$message' | /usr/sbin/ssmtp $to");
}

sub escape {
  my $address = shift;
  $address =~ s/@/\\@/g;
  return $address;
}

1;

Когда я запускаю ./maillog.pl, электронное письмо не отправляется при использовании кода в пакете Testy (тот же код работает в файле maillog.pl. Однако, если я раскомментирую Log::Dispatch::Email::SSMTP и заменю на Log::Log4perl::Appender::Screen, он сработает.

ОБНОВЛЕНИЕ #2 Если я изменю Log::Log4perl::Appender::Screen на Log::Dispatch::Screen, это тоже сработает. Так может пришёл какой-то баг в Log::Dispatch::Email?


person StevieD    schedule 03.12.2015    source источник
comment
Можете ли вы привести пример, который отражает то, как выглядит ваш код, когда вы не получаете электронное письмо? Любые советы, которые люди могут дать, ограничены, потому что они не могут видеть настоящий код.   -  person Hunter McMillen    schedule 03.12.2015
comment
Log::Dispatch и Log::Log4Perl — разные решения для ведения журнала; кажется, вы написали приложение для электронной почты для Log::Dispatch, но используете его в Log::Log4Perl..?   -  person Kenney    schedule 03.12.2015
comment
@HunterMcMillen, хорошо, я добавил весь соответствующий код.   -  person StevieD    schedule 03.12.2015
comment
@Kenney, но тот же код отлично работает при запуске непосредственно из файла maillog.pl (см. мой добавленный код выше)   -  person StevieD    schedule 03.12.2015
comment
Странный. Когда я сравнил ваш первый фрагмент с Testy.pm, единственное реальное различие — это адрес электронной почты ([email protected] против s@dondley....) — вы, вероятно, изменили его для публикации здесь, так что, вероятно, это не так?   -  person Kenney    schedule 03.12.2015
comment
@kenney, нашел проблему. Смотри ниже.   -  person StevieD    schedule 03.12.2015
comment
Ах, спасибо, что сообщили мне. Согласно документу Log::Dispatch::EMail будет сбрасывать при уничтожении. Может деструктор не вызывается при загрузке через модуль? Однако буферизация удобна для получения только одного письма за один запуск скрипта; вы можете рассмотреть другой обходной путь, например END { $appender_email->flush() }..   -  person Kenney    schedule 03.12.2015


Ответы (1)


Проблема найдена с помощью часто задаваемых вопросов по адресу нажмите здесь

По-видимому, происходит некоторая буферизация, поэтому электронные письма не отправляются немедленно, пока не будет достигнут некоторый порог количества сгенерированных сообщений. Хотя для меня до сих пор остается загадкой, почему электронные письма отправляются сразу же, когда код находится в пакете main.

Итак, вот код, который работает со свойством buffered, установленным на 0:

my $appender_email = Log::Log4perl::Appender->new(
    "Log::Dispatch::Email::SSMTP",
    threshold => "INFO",
    to => '[email protected]',
    buffered => 0,
    subject => 'Perl script message'
);
person StevieD    schedule 03.12.2015