File Coverage

blib/lib/Gaim/Log/Mailer.pm
Criterion Covered Total %
statement 52 114 45.6
branch 7 32 21.8
condition 0 6 0.0
subroutine 12 18 66.6
pod 0 4 0.0
total 71 174 40.8


line stmt bran cond sub pod time code
1             ###########################################
2             package Gaim::Log::Mailer;
3             ###########################################
4              
5 1     1   59640 use strict;
  1         3  
  1         34  
6 1     1   6 use warnings;
  1         1  
  1         37  
7 1     1   920 use Gaim::Log::Parser 0.10;
  1         243763  
  1         31  
8 1     1   867 use Gaim::Log::Finder;
  1         1018  
  1         25  
9 1     1   5 use Log::Log4perl qw(:easy);
  1         2  
  1         4  
10 1     1   1304 use URI::Find;
  1         8921  
  1         75  
11 1     1   874 use Data::Throttler;
  1         9953  
  1         34  
12 1     1   908 use Mail::DWIM qw(mail);
  1         15032  
  1         71  
13 1     1   700 use Text::TermExtract;
  1         10063  
  1         39  
14 1     1   9 use YAML qw(LoadFile);
  1         2  
  1         54  
15 1     1   7 use URI;
  1         2  
  1         1301  
16              
17             our $VERSION = "0.02";
18             our %SEEN;
19             my $name = "gaimlogmailer";
20              
21             ###########################################
22             sub new {
23             ###########################################
24 1     1 0 1100 my($class, %options) = @_;
25              
26 1         45 my($home) = glob "~";
27              
28 1         16 my $self = {
29             config_file => "$home/.$name.yml",
30             conf => {
31             min_age => 3600,
32             throttle_interval => 3600,
33             throttle_max_emails => 10,
34             logfile => undef,
35             email_to => undef,
36             languages => ['en'],
37             exclude_words => [],
38             },
39             %options,
40             };
41              
42 1         5 $self->{base_dir} = "$home/.$name";
43 1 50       20 if(! -d $self->{base_dir}) {
44 0 0       0 mkdir $self->{base_dir} or
45             LOGDIE "Cannot create $self->{base_dir} ($!)";
46             }
47              
48 1 50       20 if(-f $self->{config_file}) {
49 1         8 my $conf = LoadFile( $self->{config_file} );
50 1         19392 foreach my $key (keys %$conf) {
51 2 50       14 if(!exists $self->{conf}->{$key}) {
52 0         0 LOGDIE "Unknown configuration parameter '$key' ",
53             "in $self->{config_file}";
54             }
55 2         10 $self->{conf}->{$key} = $conf->{$key};
56             }
57              
58 1 50       6 if($conf->{exclude_words}) {
59 0         0 $self->{conf}->{exclude_words} =
60             [split ' ', $conf->{exclude_words}];
61             }
62              
63 1 50       6 if($conf->{languages}) {
64 0         0 $self->{conf}->{languages} =
65             [split ' ', $conf->{languages}];
66             }
67             } else {
68 0         0 LOGDIE "Cannot open conf file $self->{config_file} ($!)";
69             }
70              
71 0         0 $self->{conf}->{exclude_hash} = { map { $_ => 1 }
  1         9  
72 1         3 @{ $self->{conf}->{exclude_words} } };
73              
74 1 50       6 if(!defined $self->{conf}->{email_to}) {
75 0         0 LOGDIE "Mandatory parameter email_to missing in configuration.";
76             }
77              
78 1         20 $self->{throttler} = Data::Throttler->new(
79             db_file => "$self->{base_dir}/throttle",
80             interval => $self->{conf}->{throttle_interval},
81             max_items => $self->{conf}->{throttle_max_emails},
82             );
83              
84 1 50       54449 dbmopen %SEEN, "$self->{base_dir}/seen", 0644 or
85             LOGDIE "Cannot open dbm file $self->{base_dir}/seen ($!)";
86              
87             $SIG{TERM} = sub {
88 0     0   0 INFO "Exiting";
89 0         0 dbmclose %SEEN;
90 0         0 exit 0;
91 1         3599 };
92              
93 1         9 bless $self, $class;
94             }
95              
96             ###########################################
97             sub process {
98             ###########################################
99 0     0 0   my($self) = @_;
100              
101             my $finder = Gaim::Log::Finder->new(
102             callback => sub {
103 0     0     my($self, $file, $protocol, $from, $to) = @_;
104            
105 0 0         return 1 if $from eq $to;
106            
107 0           my $mtime = (stat $file)[9];
108 0           my $age = time() - $mtime;
109            
110 0 0 0       return 1 if $SEEN{$file} and
111             $SEEN{$file} == $mtime;
112            
113 0 0         if($age < $self->{mailer}->{conf}->{min_age}) {
114 0           INFO "$file: Too recent ($age)";
115 0           return 1;
116             }
117            
118 0           INFO "Processing log file: $file";
119 0           my($subject, $formatted, $epoch) = $self->{mailer}->examine($file);
120              
121 0           DEBUG "subject: $subject";
122 0           DEBUG "formatted: $formatted";
123 0           DEBUG "epoch: $epoch";
124              
125            
126 0 0         if(! $self->{mailer}->email_send($epoch, $to, $subject, $formatted)) {
127 0           DEBUG "Email couldn't be sent. Exiting";
128 0           exit 0;
129             }
130 0           $SEEN{$file} = $mtime;
131 0           });
132              
133 0           $finder->{mailer} = $self;
134 0           $finder->find();
135             }
136              
137             ###########################################
138             sub examine {
139             ###########################################
140 0     0 0   my($self, $file) = @_;
141            
142 0           my $extr = Text::TermExtract->new(
143             languages => $self->{conf}->{languages} );
144              
145 0           $extr->exclude( $self->{conf}->{exclude_words} );
146              
147 0           my $parser = Gaim::Log::Parser->new(
148             file => $file,
149             );
150              
151             # Search+delete URL processor
152 0           my @hosts = ();
153 0     0     my $urifind = URI::Find->new(sub {push @hosts, $_[0]->host();
154 0           return "";});
  0            
155            
156 0           my $content = "";
157 0           my $urifound = 0;
158            
159 0           while(my $m = $parser->next_message()) {
160 0           $content .= " " . $m->content();
161             }
162              
163 0           $urifound = $urifind->find(\$content);
164 0 0         $content = " " unless length $content;
165              
166 0           my @words = $extr->terms_extract( $content, {max => 20} );
167              
168 0           my $char = "";
169 0 0         my $subj = ($urifound ? "*L* $hosts[0] " : "");
170              
171 0   0       while(@words and
172             length($subj) + length($char . $words[0]) <= 70) {
173 0           $subj .= $char . shift @words;
174 0           $char = ", ";
175             }
176              
177 0           return($subj, $parser->as_string(), $parser->{dt}->epoch());
178             }
179              
180             ###########################################
181             sub email_send {
182             ###########################################
183 0     0 0   my($self, $epoch, $from, $subject, $text) = @_;
184              
185 0 0         if(!$self->{throttler}->try_push()) {
186 0           ERROR "Email throttled.";
187 0           return undef;
188             }
189              
190 0 0         if($self->{fake_email}) {
191 0           print <
192             ==========================================================================
193             From: $from
194             To: $self->{conf}->{email_to}
195             Subject: [gaim $from] $subject
196              
197             $text
198             ==========================================================================
199             EOT
200 0           return 1;
201             }
202              
203 0           INFO "Sending email '$subject'";
204              
205 0           mail(
206             from => "$from\@gaim",
207             to => $self->{conf}->{email_to},
208             subject => "[gaim] " . $subject,
209             text => "From: $from\n" .
210             "Date: " .
211             (scalar localtime $epoch) .
212             "\n\n$text",
213             );
214              
215 0           return 1;
216             }
217              
218            
219             1;
220              
221             __END__