diff --git a/urgent-mail-check.plx b/urgent-mail-check.plx index 6ec7268..ce9f1cf 100755 --- a/urgent-mail-check.plx +++ b/urgent-mail-check.plx @@ -1,7 +1,7 @@ #!/usr/bin/perl # urgent-mail-check.plx # -# Copyright (C) 2013, Bradley M. Kuhn +# Copyright (C) 2013, 2015, 2016, Bradley M. Kuhn # # This program gives you software freedom; you can copy, modify, convey, # and/or redistribute it under the terms of the GNU General Public License @@ -26,57 +26,61 @@ use Date::Manip; use Net::IMAP::Client; use File::Spec; use File::Temp; +use Encode qw(encode decode); -if (@ARGV != 2) { - print STDERR "usage: \n"; +my $VERBOSE = 0; +if (@ARGV != 3) { + print STDERR "usage: \n"; exit 1; } +my($SERVER, $USERNAME, $PASSWORD_FILE) = @ARGV; + my $DIR = File::Spec->catdir("$ENV{HOME}", 'tmp', '.urgent-email-displayed'); chdir($DIR) or die "unable to go to $DIR"; ###################################################################### -sub ReadRecentUrgentEmailAnnouncements ($) { - my($dir) = @_; +sub ReadRecentUrgentEmailAnnouncements ($$) { + my($dir, $server) = @_; my %info; - my $file = File::Spec->catfile($dir, 'urgent-email-announce-recent'); - open(RECENT_ALERTS, "<", $file) or die "unable to open $file for reading: $!"; + my $file = File::Spec->catfile($dir, $server . '.urgent-email-announce-recent'); + open(RECENT_ALERTS, '<:encoding(UTF-8)', $file) or die "unable to open $file for reading: $!"; my $key; - my $data = ""; foreach my $line () { chomp $line; next if $line =~ /^\s*$/; - if ($line =~ /^\s*([\d\:\-]+)\s*$/) { - my $newKey = $1; - $info{$key} = $data if defined $key; - $key = $newKey; - $data = ""; - } else { - $data .= $line; + if ($line =~ /^\s*\"(.*)\"\s*:\s*([\d\:\-]+)\s*$/) { + my($key, $date) = ($1, $2); + $info{$key} = $date if defined $key; } } close RECENT_ALERTS; die "error($?) reading $file: $!" unless $? == 0; - $info{$key} = $data if (defined $key); # Grab last one. - return \%info; } ###################################################################### -sub WriteRecentUrgentEmailAnnouncements ($$) { - my($dir, $info) = @_; +sub WriteRecentUrgentEmailAnnouncements ($$$) { + my($dir, $server, $info) = @_; - my $file = File::Spec->catfile($dir, 'urgent-email-announce-recent'); - open(RECENT_ALERTS, ">", $file) or die "unable to open $file for reading: $!"; + my $file = File::Spec->catfile($dir, $server . '.urgent-email-announce-recent'); + print STDERR "writing to $file\n" if $VERBOSE; + open(RECENT_ALERTS, '>:encoding(UTF-8)', $file) or die "unable to open $file for reading: $!"; foreach my $key (sort keys %$info) { - print RECENT_ALERTS "$key\n$info->{$key}\n"; + print STDERR "\"$key\": $info->{$key}\n" if $VERBOSE; + print RECENT_ALERTS "\"$key\": $info->{$key}\n"; } close RECENT_ALERTS; die "error($?) writing $file: $!" unless $? == 0; + print STDERR "Closed $file\n" if $VERBOSE; } ###################################################################### # Test if network is up +if (-f "$ENV{HOME}/.shoddy-network") { + print "\${color5}Shoddy Network, no urgent email check!\n"; + exit 0; +} system('/bin/ping -q -w 20 -c 5 pine.sfconservancy.org > /dev/null 2>&1'); if ($? != 0) { @@ -84,31 +88,30 @@ if ($? != 0) { exit 0; } -if (not -f $ARGV[1]) { - print "\${color5}File $ARGV[1] not readable!\n"; +if (not -f $PASSWORD_FILE) { + print "\${color5}File $PASSWORD_FILE not readable!\n"; exit 0; } -my $output = ""; my $record = ""; -my $info = ReadRecentUrgentEmailAnnouncements($DIR); +my $info = ReadRecentUrgentEmailAnnouncements($DIR, $SERVER); # open a connection to the IMAP server use Net::IMAP::Client; -open(PW, "<", $ARGV[1]) or die "unable to open $ARGV[0] to find password!"; +open(PW, "<", $PASSWORD_FILE) or die "unable to open $PASSWORD_FILE to find password!"; my %passwords; while (my $line = ) { - die "invalid line in password file: $ARGV[1]" + die "invalid line in password file: $PASSWORD_FILE" unless $line =~ /^\s*(\S+)\s+(\S+)\s*$/; $passwords{$1} = $2; } close PW; my $imap = Net::IMAP::Client->new( - server => 'pine.sfconservancy.org', - user => $ARGV[0], - pass => $passwords{$ARGV[0]}, + server => $SERVER, + user => $USERNAME, + pass => $passwords{$USERNAME}, ssl => 1, # (use SSL? default no) ssl_verify_peer => 1, # (use ca to verify server, default yes) # ssl_ca_file => '/etc/ssl/certs/certa.pm', # (CA file used for verify server) or @@ -126,51 +129,80 @@ my $summaries = $imap->get_summaries($messages); use Data::Dumper; +my(%noticeOutput); +my $now = ParseDate("now"); foreach my $summary (@{$summaries}) { - my $now = ParseDate("now"); my($who, $subject) = ($summary->{from}->[0]->name, $summary->subject); my $datetime = ParseDate($summary->date); - my $ago = Delta_Format(DateCalc($datetime, $now), 0, "%dt days"); - $ago = Delta_Format(DateCalc($datetime, $now), 0, "%ht hours") - if (defined $ago and $ago =~ /0 days/); - $ago = Delta_Format(DateCalc($datetime, $now), 0, "%mt minutes") - if (defined $ago and $ago =~ /0 hours/); - $ago = Delta_Format(DateCalc($datetime, $now), 0, "%st seconds") - if (defined $ago and $ago =~ /0 minutes/); + my $output = ""; + my $ago = Delta_Format(DateCalc($datetime, $now), "approx", 0, "%dt days"); + $ago = Delta_Format(DateCalc($datetime, $now), "approx", 0, "%ht hours") + if (defined $ago and $ago =~ /(^|\s+)0\s+day/); + $ago = Delta_Format(DateCalc($datetime, $now), "approx", 0, "%mt minutes") + if (defined $ago and $ago =~ /(^|\s+)0\s+hour/); + $ago = Delta_Format(DateCalc($datetime, $now), "approx", 0, "%st seconds") + if (defined $ago and $ago =~ /(^|\s+)0\s+minute/); $ago = "" if not defined $ago; + $subject = "" unless defined $subject; + $subject = (split('\n', $subject))[0]; $subject =~ s/^\s*Re\s*:\s*//i; - my $record = "$who about $subject"; - $output .= "\${font Inconsolata:size=13}$ago ago from $record\n"; - - my $alreadyDone = 0; - foreach my $key (keys %$info) { - $alreadyDone = (($info->{$key} eq $record) and - (Delta_Format(DateCalc($key, $now), 0, "%mt") < 14400)); - last if $alreadyDone; - } - unless ($alreadyDone) { - $info->{$now} = $record; - my $fh = File::Temp->new(); - $fh->unlink_on_destroy( 1 ); - my $fname = $fh->filename; - print $fh "Urgent email: "; - print $fh $record; - $fh->close(); - system("$ENV{HOME}/bin/myosd", $fname); - system('/usr/bin/notify-send', '-u', 'critical', '-t', '300000', - 'Urgent Email', $record); - system("$ENV{HOME}/bin/myspeakbyfile", $fname) - unless -f "$ENV{HOME}/.silent-running"; - } + next if not defined $subject or $subject =~ /^\s*$/; + $who = "unknown" unless defined $who; + my $record = encode('UTF-8', "$who about $subject"); + + $noticeOutput{$record}{output} = $output; + $noticeOutput{$record}{datetime} = $datetime; + $noticeOutput{$record}{who} = $who; + $noticeOutput{$record}{subject} = $subject; } -WriteRecentUrgentEmailAnnouncements($DIR, $info); +my $olderCount = 0; +my $oldestNow = $now; +my $SEVEN_DAYS_AGO = DateCalc($now, "-7 days"); +my $allOutput = ""; +foreach my $record (sort {$noticeOutput{$a}{datetime} cmp $noticeOutput{$b}{datetime} } keys %noticeOutput ) { + my $alreadyDone = (defined $info->{$record} ) ? $info->{$record} : undef; + #and (Delta_Format(DateCalc($info->{$record}, $now), "approx", 0, "%ht") < 96)); + # uncomment above and put into expression if you want reminders on older emails you're ignoring in urgent. + $info->{$record} = $now; + if ($noticeOutput{$record}{datetime} lt $SEVEN_DAYS_AGO) { + $olderCount++; + $oldestNow = $alreadyDone if defined $alreadyDone and $alreadyDone lt $oldestNow; + next; + } else { + $allOutput .= $noticeOutput{$record}{output}; + } + next if defined $alreadyDone; -print "\$hr\n\${font :size=17}Urgent Emails:\n$output\$hr" if ($output ne ""); + $info->{$record} = $now; + my $fh = File::Temp->new(); + $fh->unlink_on_destroy( 1 ); + my $fname = $fh->filename; + print $fh "Urgent email: "; + print $fh $record; + $fh->close(); +# system("$ENV{HOME}/bin/myosd", $fname); + system('/usr/bin/notify-send', '-u', 'critical', '-t', '300000', + 'Urgent Email', $record); + system("$ENV{HOME}/bin/myspeakbyfile", $fname) + unless -f "$ENV{HOME}/.silent-running"; +} +WriteRecentUrgentEmailAnnouncements($DIR, $SERVER, $info); + +if ($allOutput ne "") { + print "\$hr\n\${font :size=17}Urgent Emails:\n$allOutput"; + print "\${font Inconsolata:size=13}... and $olderCount emails older than 7 days\n" if $olderCount > 0; + print "\$hr"; +} +my $hoursSinceNotify = Delta_Format(DateCalc($oldestNow, $now), "approx", 0, "%ht"); +if ($olderCount > 0 and $hoursSinceNotify > 1) { + system('/usr/bin/notify-send', '-u', 'critical', '-t', '300000', + 'LONG PENDING URGENT EMAIL', + "$olderCount urgent emails in folder older than 7 days (last remind: $hoursSinceNotify)"); +} ############################################################################### # # Local variables: # compile-command: "perl -c urgent-mail-check.plx" # End: -