#!/usr/bin/perl -W #------------------------------------------------------------------------------- # nag-reminder.pl (C) 2006 T.Birnthaler OSTC GmbH # $Id: nag-reminder.pl,v 1.5 2006-05-17 15:32:03 tsbirn Exp $ #------------------------------------------------------------------------------- # Horde-Aufgaben überwachen und bei Ablauf der Warnzeit eine Erinnerungs-Mail # schicken (nur 1x!). Dieser Vorgang wird in der Aufgaben-Beschreibung vermerkt, # indem der minimale(!) Erledigungs-Zeitpunkt dort eingetragen wird. # # Ändert der Benutzer die Erledigungs-Zeitpunkt ab, wird dies erkannt, die # Erinnerungs-Mail erneut verschickt und die Aufgaben-Beschreibung angepasst. # # Als externes Programm nur durch Zugriff auf die entsprechenden DB-Tabellen # realisiert, da der Einbau in die Horde-NAG-Infrastruktur zu komplex erschien. # # Getestet mit Horde-3.1.1 und NAG-H3-2.1. #------------------------------------------------------------------------------- # Tabelle "horde.nag_tasks": +--- Für SELECT/UPDATE notwendig # +----------------+--------------+ | +--- Für Mail-Versand notwendig # | Field | Type | | | +--- Für Mail-Inhalt notwendig # +----------------+--------------+ | | | # | task_id | varchar(32) | * - - Aufgaben-ID (Zugriffsschlüssel) # | task_owner | varchar(255) | * * - Aufgaben-Besitzername # | task_name | varchar(64) | * * * Aufgaben-Name # | task_uid | varchar(255) | - - - User-ID # | task_desc | text | * * * Aufgaben-Beschreibung # | task_due | int(11) | * * * Erledigungszeitpunkt UNIX-Timestamp # | task_priority | int(11) | * * * Aufgaben-Priorität # | task_category | varchar(80) | * * * Aufgaben-Kategorie # | task_completed | smallint(6) | * - - Erledigt # | task_alarm | int(11) | * * - Vorwarnzeit in Minuten # | task_private | int(11) | - - - Privat (???) # +----------------+--------------+ #------------------------------------------------------------------------------- use strict; # Module use DBI; use Mail::Mailer; # Produktion oder Debugging (Schalter "-p") my $dbg = 1; my $cond = "AND task_name LIKE '%xyz%'" if ($dbg); if (@ARGV > 0 and $ARGV[0] eq "-p") { $dbg = 0; $cond = ""; } # Datenbank-Anmeldedaten my $dbhost = "127.0.0.1"; my $dbport = "3306"; my $dbname = "horde"; my $tblname = "nag_tasks"; my $username = "USER"; my $password = "GEHEIM"; # Aktueller Zeitpunkt my $time = time(); print "TIME: $time\n" if ($dbg); # SELECT-Statement für noch nicht erledigte Aufgaben im richtigen Zeitraum my $stm = " SELECT task_id, task_owner, task_name, task_desc, task_due, task_priority, task_category, task_alarm FROM ${tblname} WHERE task_completed = 0 AND $time >= task_due - task_alarm * 60 AND $time < task_due $cond "; # Datenbank-Verbindung öffnen #;host=127.0.0.1;port=3306"; my $db = DBI->connect("dbi:mysql:database=$dbname;host=$dbhost;port=$dbport", $username, $password) or die(DBI::errstr); # Passende nicht erledigte Aufgaben aus Datenbank abfragen print "SELECT: $stm\n" if ($dbg); my $sql = $db->prepare($stm) or die $db->errstr; $sql->execute() or die $db->errstr; # Passende nicht erledigte Aufgaben von Datenbank holen my @todo; while (my $row = $sql->fetchrow_hashref) { my $id = $row->{'task_id'}; my $owner = $row->{'task_owner'}; my $name = $row->{'task_name'}; my $desc = $row->{'task_desc'}; my $due = $row->{'task_due'}; my $priority = $row->{'task_priority'}; my $category = $row->{'task_category'}; my $alarm = $row->{'task_alarm'}; printf "FOUND: $id, $owner, $name, $priority, $category, $desc\n" if ($dbg); print "due: $due, alarm: $alarm, time: $time," if ($dbg); print " diff1: ", $due - $time - $alarm * 60, "," if ($dbg); print " diff2: ", $due - $time, "\n" if ($dbg); # Alarm schon mal ausgelöst? # (= Text "ERINNERUNG VERSANDT (TIMESTAMP)" am Beschreibungsende) if ($desc =~ /ERINNERUNG VERSANDT/) { # Sendezeit der alten Mail vor aktueller minimaler Alarmzeit? # -> Nochmal senden (Text vorher aus Beschreibung entfernen!) my ($sentdate) = ($desc =~ /ERINNERUNG VERSANDT \(([0-9]+)\)/); print "SENTDATE: $1\n" if ($dbg); next if ($sentdate >= $due - $alarm * 60); # Hilfs-Text aus Beschreibung entfernen $desc =~ s/\n*ERINNERUNG VERSANDT.*$//s; print "NEW-DESC: $desc" if ($dbg); } # Merken, erst nach Abarbeitung des SELECT zugehörige Mails versenden print "TODO ($id, $owner, $name, $due, $priority, $category, $alarm, $desc)\n" if ($dbg); push @todo, [ $id, $owner, $name, $desc, $due, $priority, $category, $alarm ]; } # Mail für gefundene Aufgaben verschicken (und in DB eintragen) &HandleFoundTasks(@todo); # Datenbank-Verbindung schließen $db->disconnect(); #------------------------------------------------------------------------------- # Für gefundene zeitlich passende Aufgaben Erinnerungsmail verschicken (nur 1x!) # und in der Aufgaben-Beschreibung vermerken (WICHTIG: min. Erinnerungszeit!). # 1-N: Task-Liste mit Array-Referenzen auf (id, owner, name, due, alarm, desc) #------------------------------------------------------------------------------- sub HandleFoundTasks { foreach (@_) { my ($id, $owner, $name, $desc, $due, $priority, $category, $alarm) = @$_; my $minimum = $due - $alarm * 60; # Erinnerungsmail in Beschreibung vermerken my $stm = " UPDATE ${tblname} SET task_desc = '$desc\n\nERINNERUNG VERSANDT ($minimum)' WHERE task_id = '$id' "; print "SQL: $stm\n" if ($dbg); $sql = $db->prepare($stm); $sql->execute() or die $db->errstr; SendMail($owner, $name, $desc, $due, $priority, $category, $alarm); } } #------------------------------------------------------------------------------- # Erinnerungs-Mail bzgl. zu erledigender Aufgabe verschicken. # 1: Wer (Text) # 2: Aufgaben-Name (Text) # 3: Aufgaben-Beschreibung (Text) # 4: Zieldatum (UNIX-Timestamp) # 5: Priorität (1-5) # 6: Kategorie (Text) # 7: Alarm-Zeitraum vorher (Minuten) #------------------------------------------------------------------------------- sub SendMail { my ($owner, $name, $desc, $due, $priority, $category, $alarm) = @_; print "SendMail($owner, $name, $desc, $due, $priority, $category, $alarm)\n" if ($dbg); # Due-Timestamp -> Ziel-Zeitpunkt my ($sec, $min, $hour, $day, $mon, $year) = localtime($due); $year += 1900; $mon += 1; my $datetime = sprintf("%d.%d.%d %d:%02d", $day, $mon, $year, $hour, $min); # Mail verschicken my $mailer = new Mail::Mailer; $mailer->open({ "From" => "horde@ostc.de", "To" => $owner, "Subject" => "Erinnerung: Aufgabe '$name' ($datetime, $priority, $category)!", }); print $mailer $desc; # desc = Body $mailer->close; }