Scripting Evolution

Eine Möglichkeit, wie man mit Evolution verwaltete Mails automatisch durch ein Skript verarbeiten lassen kann.



Vorwort

Das hier beschriebene Verfahren wurde erfolgreich mit Evolution 1.2.1 unter Linux (Mandrake 9.0) getestet. Ob es mit älteren oder neueren Evolution-Versionen und/oder unter anderen Betriebssystemen funktioniert ist nicht bekannt, Hinweise diesbezüglich wären eine nette Geste.

Warum?

Wie kommt man auf die Idee Mails durch ein Skript verarbeiten zu lassen? In meinem Fall waren es tägliche Datenbank-Backups die mich via Mail erreichen, in einem denkbar simplen Format: Der Mailbody besteht nur aus fertigen SQL-Anweisungen, welche ich immer per Hand in den phpMyAdmin kopiert habe. Das täglich von Hand zu machen ist wie ich finde jedoch recht stupide, also musste eine Lösung her - die Skript-Idee war geboren.

Grundsätzliches

Beim betrachten des Verzeichnisses ~/evolution fiel mir eins ziemlich schnell auf: Zu kompliziert. Damit stand fest, dass vor der Erstellung des Skriptes erstmal Evolution nach Möglichkeit umkonfiguriert werden musste. Für das Skript brauchte ich eine einfach zu parsende Verzeichnisstruktur, welche sich schließlich im mh-Format fand - mehr dazu später. Ein Feature welches ich als wichtig empfand war weiterhin, dass bereits verarbeitete Mails gelöscht werden. Mit dem mh-Format war auch das kein Problem.

Vorbereitungen

Um nur Mails an das Skript zu übergeben die ich auch wirklich verarbeiten will griff ich zu einem neuen Ordner, welcher im Evolution einfach mit einem Rechtsklick in der Ordneransicht angelegt werden kann. Den Ordner habe ich innerhalb des Eingangs angelegt, durch einen weiteren Rechtsklick auf den neuen Ordner kam ich in die Eigenschaften. Dort stellte ich das Speicherformat auf mh um, gleichzeitig schaltete ich die unnötige Indizierung - die Mails werden eh immer gelöscht - ab. Fehlt nur noch ein Filter (Menü Werkzeuge -> Filter) der die passenden Mails in diesen Ordner verschiebt, schon sind die Vorbereitungen abgeschlossen.

Skript-Theorie

Was muss das Skript machen? Auf Grund des mh-Formats liegen sämtliche Mails als einzelne Dateien in einem einzelnen Ordner vor, die Devise heisst also: Verzeichnis auslesen, Dateien auswerten, fertig. Das auswerten der einzelnen Dateien ist in simplen Fällen wie meinem auch kein Problem, dank des sauberen Aufbaus von E-Mails. Die sind nämlich so spezifiziert, dass die erste leere Zeile (also die erste Zeile die nur einen weiteren Zeilenumbruch enthält) das Ende der Header markiert, danach kommen in „plain text”-Mails nur noch Nutzdaten. Ich musste also jede Datei einfach nur Zeilenweise durchgehen und alles nach der ersten Leerzeile als Nutzdaten übernehmen. Wegen der textlastigen Aufgabe entschied ich mich für Perl als Skriptsprache.

das Skript

Im folgenden sei das Skript gezeigt (Erklärungen folgen nach dem Skript), die im Skript enthaltenen Kommentare sollten zum grundsätzlichem Verständnis ausreichen. Das gezeigte Skript ist bei mir im Einsatz und schiebt Daten in meine lokale Datenbank, daher der MySQL-Teil am Ende. Je nachdem was man selbst mit seinen Mails machen will muss man hier Hand anlegen. Nur noch eine Warnung bevor das Skript kommt: Die hier gezeigte Version löscht ausgewertete Mails, zum testen sollte man die betreffende Zeile (durch einen Warn-Kommentar erkenntlich gemacht) vorerst auskommentieren!

#!/usr/bin/perl -w

# (c) 2003 Robert Weiler, <http://www.robwei.de/>
# This script comes WITH ABSOLUTELY NO WARRANTY. USE AT OWN RISK.
# See the GPL <http://www.gnu.org/licenses/gpl.html> for details.



### benötigte Module einbinden
use strict;
use DBI;

### die drei folgenden Variablen konfigurieren das Skript.
my $user   = "test";
my $box    = "Inbox";
my $folder = "Skript";

### aus den Variablen wird eine Pfadangabe gebastelt
my $path = "/home/$user/evolution/local/$box/subfolders/$folder/mbox";

### prüfen ob der Pfad ein Verzeichnis darstellt und lesbar ist
if (-d $path  and  -r $path) {
    ### weitere benötigte Variablen deklarieren
    my (@filelist, $filename, @mails);

    ### das Mail-Verzeichnis auslesen
    opendir(DIR, $path) or die "$!\n";
    @filelist = readdir(DIR) or die "$!\n";
    closedir(DIR);

    ### nur Maildateien in die "zu bearbeiten"-Liste aufnehmen
    foreach $filename (@filelist) {
        if ($filename =~ /\d+/) {
            push(@mails, $filename);
        }
    }

    ### Wurden eine oder mehrere Mails gefunden?
    if (scalar(@mails) > 0) {
        ### weitere benötigte Variablen deklarieren
        my ($is_content, @content, $line);

        ### kurze Statusmeldung ausgeben
        printf "Processing %d mail(s)...\n", scalar(@mails);

        ### die "zu bearbeiten"-Liste durchgehen
        foreach $filename (@mails) {
            ### Ist die Datei lesbar?
            if (-r "$path/$filename") {
                ### Statusvariable zurücksetzen, zeigt an ob schon Nutzinhalt gelesen wird
                $is_content = 0;

                ### Datei öffnen und durchgehen
                open(MAIL, "$path/$filename") or die "$!\n";
                while ($line = <MAIL>) {
                    ### Nutzinhalt lesen
                    if ($is_content == 1) {
                        push(@content, $line);
                    }

                    ### leere Zeile -> Statusvariable setzen
                    if ($line =~ /^\n$/) {
                        $is_content = 1;
                    }
                }
                close(MAIL);
                ### !ACHTUNG!  Datei löschen
                unlink("$path/$filename");
            }
            else {
                printf "   Error: The file %d could not be read.\n", $filename;
            }
        }

        ### Wurde Nutzinhalt ausgelesen?
        if (scalar(@content) > 0) {
            ### ein letztes mal Variablen deklarieren
            my ($dbh, $query);

            ### zu MySQL verbinden, die SQL-Befehle ausführen, die Verbindung wieder trennen
            $dbh = DBI->connect("DBI:mysql:datenbank:localhost", "user", "passwort") or die "$!\n";
            foreach $line (@content) {
                chomp($line);
                if ($line ne "") {
                    $query = $dbh->prepare($line);
                    $query->execute();
                    $query->finish();
                }
            }
            $dbh->disconnect() or warn "$!\n";
        }
        else {
            print "No content was extracted - nothing to do.\n";
        }

        ### wir haben fertig - Statusmeldung ausgeben
        print "Mail(s) processed.\n";
    }
    else {
        print "No mail to process.\n";
    }
}
else {
    print "Please check your variables. The path\n$path\nis no directory and/or not readable.\n";
}

Wie man sieht folgt das Skript den simplen Vorgaben der oben aufgestellten Theorie. Um das Skript für seine eigenen Zwecke anzupassen muss man lediglich das Array @content anders verarbeiten, natürlich müssen auch die Konfigurationsvariablen angepasst werden.

Konfiguration

$user: Diese Variable enthält den Namen des Benutzers dessen Mails verarbeitet werden sollen. Ist mit dem Login-Namen identisch.

$box: Enthält den Namen des Ordners unter dem der auszuwertende Ordner liegt. Hier ist zu beachten das Evolution trotz der deutschen Bezeichnungen in der Ordnerübersicht („Eingang”, „Ausgang” etc.) auf Dateisystemebene englische Namen benutzt („Inbox”, „Outbox” etc.), hier ist ein Blick in ~/evolution/local zu empfehlen.

$folder: Der Name des auszuwertenden Ordners. Hier werden die Namen von Evolution 1:1 übernommen, heisst der Ordner in der Ordnerübersicht „automatische Verabeitung” dann heisst er auch auf Dateisystemebene so.

Wie man in der nächsten Anweisung nach der Konfiguration sieht, werden die Variablen einzig und allein dafür gebraucht um eine Pfadangabe zusammen zu stellen. Der versierte Benutzer kann hier natürlich auch sofort seine Pfadangabe eintragen.

Automatisierung

Zur endgültigen Automatisierung empfiehlt es sich, das Skript von einem der diversen Startup- oder Login-Skripte (etwa /etc/profile und Konsorten) starten zu lassen. Das hat zudem den Vorteil das man im Evolution auf keine „Geistermails” trifft - läuft das Skript während Evolution läuft verschwinden die gelöschten Mails nicht aus der Übersicht, versucht man eine der gelöschten Mails zu lesen gibt es eine Fehlermeldung.


(c) 2003 Robert Weiler, <http://robwei.de/>.
Letzte Änderung: 18. Februar 2003, 04:03:57 Uhr.
HTML 4.01. CSS Level 2. — GFDL. CC A-NC-SA 1.0.