#!/usr/bin/perl -w use strict; use Date::Parse; use Email::Date::Format qw(email_date); use File::Slurp qw(slurp); use Getopt::Long; use Mail::Sendmail; use POSIX qw(strftime); # outgoing SMTP server my $SMTP = 'localhost'; # who this goes to my $ME = 'dmarti@zgp.org'; my $TODO_FOLDER = '/home/dmarti/Maildir/INBOX'; my @TODOS_IN = ($TODO_FOLDER, '/home/dmarti/Maildir/pim', ); my $When = ''; my $Verbose = 0; my $Priority = ''; my $AlarmInterval; GetOptions ("date|dtstart|d=s" => \$When, "priority|p=s" => \$Priority, "alarm|a:s" => \$AlarmInterval, "verbose|v" => \$Verbose); if (defined($AlarmInterval) and not $AlarmInterval) { $AlarmInterval = 600; } my $what = join (' ', @ARGV); my $athost = $1 if $ME =~ /@(.+)$/; my $message_id = join ('.', time(), $$, $athost); my $show_date = strftime("%e %b", localtime); if ($AlarmInterval) { print "doing alarm"; show_alarms($AlarmInterval); exit(0); } elsif ($what !~ /\S/) { show_todos(); exit(0); } my %message = ( 'From' => "$show_date <$ME>", 'To' => $ME, 'Date' => email_date(), 'Subject' => $what, 'Message-ID' => "<$message_id>", 'X-Todo' => 'new item', ); if ($When) { $message{'X-Dtstart'} = email_date(str2time($When)); } if ($Priority) { $message{'X-Priority'} = $Priority; } if (!write_direct()) { print STDERR "\n"; $message{'smtp'} = $SMTP; sendmail ( %message ) or die $Mail::Sendmail::error; } sub show_alarms { my $interval = shift; my $now = time(); my @items = get_items(@TODOS_IN); foreach my $item (sort {$a->{'sort-date'} <=> $b->{'sort-date'}} @items) { next if !exists($item->{'X-Dtstart'}); next if $item->{'sort-date'} > $now + $interval; print $item->{'sort-date'}; print_item($item); } } sub show_todos { my @items = get_items(@TODOS_IN); my %priorities = (); foreach my $item (@items) { if ($item->{'X-Priority'}) { $priorities{$item->{'X-Priority'}} = 1; } } # calendar items print "Calendar items\n--------------\n"; my $cal_count = 0; foreach my $item (sort {$a->{'sort-date'} <=> $b->{'sort-date'}} @items) { next if !exists($item->{'X-Dtstart'}); print_item($item); $cal_count++; } print "No calendar items.\n" if !$cal_count; print "\n"; # non-calendar items foreach my $p (sort keys(%priorities)) { print $p, "\n", '-' x length($p), "\n"; foreach my $item (sort {$a->{'sort-date'} <=> $b->{'sort-date'}} @items) { next if exists($item->{'X-Dtstart'}); next if $item->{'X-Priority'} ne $p; print_item($item); } print "\n"; } print "\n"; } sub print_item { my $item = shift; if (exists($item->{'X-Dtstart'})) { print $item->{'X-Dtstart'}, " "; } print $item->{'Subject'}, "\n"; if (exists($item->{'content'})) { foreach my $line (split(/\n/, $item->{'content'})) { print " ", $line, "\n"; } } } sub write_direct { my $dest; if (-d "$TODO_FOLDER/new") { $dest = "$TODO_FOLDER/new"; } elsif (-d $TODO_FOLDER) { $dest = $TODO_FOLDER; } else { return undef; } open (FCC, "> $dest/$message_id") or return undef; foreach my $key (keys(%message)) { print FCC "$key: $message{$key}\n" or return undef; } close(FCC) or return undef; return(1); } sub get_items { my @todos_in = @_; my @result = (); foreach my $dir (@todos_in) { opendir (my $dh, $dir) or die "Can't open $dir"; foreach my $file (readdir($dh)) { if (-d "$dir/$file" and ($file eq 'cur' or $file eq 'new')) { push(@result, get_items("$dir/$file")); } next if !-r "$dir/$file" or !-f "$dir/$file"; my $content = slurp("$dir/$file"); my $text; my $headers; ($headers, $text) = (split (/\n\n/, $content, 2)); if ($headers =~ /^X-Todo/mi or $headers =~ /^X-Dtstart/mi) { my %item = (); foreach my $line (split(/\n/, $headers)) { my $k; my $v; ($k, $v) = split(/:\s+/, $line, 2); $item{$k} = $v; if ($k eq 'X-Dtstart') { $item{'sort-date'} = str2time($v); } elsif ($k eq 'Date' and !exists($item{'sort-date'})) { $item{'sort-date'} = str2time($v); } } $item{'X-Priority'} = 'z' if !exists($item{'X-Priority'}); $item{'X-Priority'} = uc($item{'X-Priority'}); if (defined($text) and $text =~ /\S/) { $item{'content'} = $text; } push (@result, \%item); } } } return @result; }