Log-Dispatch-Email-Async
view release on metacpan or search on metacpan
lib/Log/Dispatch/Email/Async.pm view on Meta::CPAN
package Log::Dispatch::Email::Async;
use 5.010;
use strict;
use warnings; # FATAL => 'all';
# use Modern::Perl;
use Carp;
########################################################################################
# TODOs
# - add option to silenty fail, not croak, upon network unavailability
# - in tests
# - complete test TODOs
# - group tests into sub-groups, files? or simplify with only 1 test?
# - write creation-only tests sub-group after ping() - NOT POSSIBLE
# - change 'detele enails' to 'move to trash - for gmail'
# - seperate ask() into a own module - NOT NEEDED ANYMORE
# - hierarchical args struct? how to self address as in <domain>?
# - final string in ask() should show secs at close instead of full value
# - shorten default replys in final string to fit in line
########################################################################################
use threads;
use Thread::Queue;
use Mail::Sender;
use Log::Dispatch::Email;
use parent 'Log::Dispatch::Email';
our $VERSION = '0.01';
sub new {
my ( $proto, %params ) = @_;
my $class = ref $proto || $proto;
my $self = bless {}, $class;
$self->_basic_init( %params );
$self->{debug_mode} = $params{debug_mode} || 0;
delete $params{debug_mode} if exists $params{debug_mode};
say "creating ", ref( $self ) if $self->{debug_mode} >= 3;
$self->{timeout} = $params{timeout} || 30;
delete $params{timeout} if exists $params{timeout};
$self->{thread_count} = $params{thread_count} || 2;
delete $params{thread_count} if exists $params{thread_count};
$self->{stack_size} = $params{stack_size} || 4;
delete $params{stack_size} if exists $params{stack_size};
$self->{stack_size} = 4 if $self->{stack_size} < 4;
# threads->set_stack_size( $self->{stack_size} * 4096 );
$self->{ident} = 'object';
$self->{tid} = threads->tid();
$self->{ndx} = 0;
$self->{count} = 0;
$self->{mailer} = Mail::Sender->new( \%params );
if ( ref( $self->{mailer} ) eq 'Mail::Sender' ) {
say ref($self), "\tcreated ", ref( $self->{mailer} ) if $self->{debug_mode} >= 3;
} else {
croak ref($self), ": cannot create Mail::Sender: $Mail::Sender::Error"
}
lib/Log/Dispatch/Email/Async.pm view on Meta::CPAN
$self->{mailq}->end();
my @left = ();
unless ( $timeleft ) {
$_->kill('TERM') for threads->list( threads::running );
my $args; push @left, $args while defined ($args = $self->{mailq}->dequeue());
}
my $sent = 0;
for my $n ( 1 .. $self->{thread_count} ) {
$sent += $self->{thread}[$n]->join();
say ref($self), ": thread ", $self->{thread}[$n]->tid(), " has been joined"
if $self->{debug_mode} >= 2;
}
if ( $self->{count} != $sent ) { # number queued in main vs. total sent from all threads
my $left = scalar(@left)." emails\n\t".join("\n\t", map {$_->{subject}} @left);
carp ref($self), ": queued $self->{count}; sent $sent; throwing away after $self->{timeout} secs, $left\n";
} else {
say ref($self), ": closing $self->{ident} \\w tid $self->{tid} after $self->{count} emails queued"
if $self->{debug_mode} >= 1;
}
# unless ( $timeleft ) {
# $_->kill('TERM') for threads->list( threads::running );
# }
# $self->{mailer}->Close(1);
# $self->{mailq}->end();
# my ( $sent, @left, $args ) = ( 0, () );
# push @left, $args while defined ($args = $self->{mailq}->dequeue());
# for my $n ( 1 .. $self->{thread_count} ) {
# $sent += $self->{thread}[$n]->join();
# say ref($self), ": thread ", $self->{thread}[$n]->tid(), " has been joined" if $self->{debug_mode} >= 1;
# }
# if ( $self->{count} != $sent ) { # number queued in main vs. total sent from all threads
# my $left = scalar(@left)." emails\n\t".join("\n\t", map {$_->{subject}} @left);
# carp ref($self), ": queued $self->{count}; sent $sent; throwing away $left\n";
# } else {
# say ref($self), ": closing $self->{ident} \\w tid $self->{tid} after $self->{count} emails queued"
# if $self->{debug_mode} >= 1;
# }
} else {
say ref($self), ": closing $self->{ident} \\w tid $self->{tid} after $self->{count} emails sent"
if $self->{debug_mode} >= 1;
}
}
1; # End of Log::Dispatch::Email::Async
__END__
=head1 NAME
Log::Dispatch::Email::Async - A L<Log::Log4Perl> appender for async email
=head1 VERSION
Version 0.01
=head1 SYNOPSIS
#!/usr/bin/perl
use Modern::Perl;
use Log::Log4perl qw/:levels/;
use Log::Log4perl::Layout;
use Proc::Daemon;
Log::Log4perl::init( 'log4perl.conf' );
my $fa = Log::Log4perl->appender_by_name( 'File' );
my $logger = Log::Log4perl->get_logger( 'main' );
Proc::Daemon::Init( {
dont_close_fh => [ $fa->{LDF}{fh}, ], # for File log appender
dont_close_fd => [ 1, 2, ], # for Screen log appender
} );
my $email_appender = Log::Log4perl::Appender->new(
'Log::Dispatch::Email::Async',
# options for Log::Dispatch::Email::Async
timeout => 30, # optional, default 30 secs
thread_count => 2, # optional, default 2 thread
stack_size => 16, # optional, default 16 kilobyte
debug_mode => 0, # optional, default 0
# options for Mail::Sender
smtp => 'smtp.example.com',
port => 587,
auth => 'LOGIN',
tls_required => 1,
authid => 'username',
authpwd => 'password',
# options for Log::Dispatch::Email
buffered => 0,
subject => "message logged from '$0'",
from => 'sender@example.com',
to => 'receipent@cpan.org', # reqd.
# options for Log::Dispatch::Output
name => 'Email', # reqd.
min_level => 1,
max_level => 5,
);
$email_appender->layout(
Log::Log4perl::Layout::PatternLayout->new('%p: %m%n%l' );
$logger->add_appender( $email_appender );
$logger->level($INFO);
$logger->info( "start $0\n\nreceipient@domain.org\n\nMessage body . . ." );
my $RUN = 1;
$SIG{TERM} = sub { $RUN = 0; };
while ( $RUN ) {
. . .
}
=head1 DESCRIPTION
=head2 Introduction
( run in 1.304 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )