mutt und horde/turba

Mein Lieblings-Mailclient ist ja immer noch mutt. An viele GUI-Programme habe ich mich mittlerweile gewöhnt[1. Es gibt natürlich auch schöne Kombinationen mit der Mächtigkeit und Eleganz der Kommandozeile und der Optik einer GUI, siehe z.B. vimperator], aber mutt bin ich treu geblieben. Unterwegs ist das immer so eine Sache, weil man nicht überall einen ssh-Client findet, deswegen nutze ich auch noch Horde. Der andere große Vorteil von Horde ist, dass es für mich die einzige wirklich funktionierende Lösung darstellt, Kalender und Adressbuch mit meinem Telefon zu synchronisieren.

Aber wie komme ich jetzt von mutt aus an die eMail-Adressen, die bei horde/turba in der Datenbank stehen? Ein bisschen scrooglen hilft: es gibt etliche Anleitungen, wie man Turba dazu bringt, die Adressen auf einem LDAP-Server zu speichern. Von da aus kann man sie dann wunderbar (dafür gibt es jede Menge fertiger Scripte) mutt zur Verfügung stellen. Ich war schon drauf und dran, LDAP zu installieren, obwohl mir klar war, dass Aufwand und Nutzen in keinem günstigen Verhältnis stehen.

Es geht natürlich auch viel einfacher: Horde speichert doch sowieso alles in einer Datenbank (bei mir z.B. MySQL), warum dann den Umweg über einen solchen Klotz am Bein? Also habe ich ein kleines Perl-Script gehackt, was einfach die Daten aus MySQL extrahiert und mutt im gewünschten Format liefert. Natürlich möchte ich euch den Code nicht vorenthalten.

#!/usr/bin/perl

# query_turba.pl, last edited: 5.1.2012
#
# This is a quick'n'dirty query script for mutt. It queries a mysql database
# working as a backend for Turba/Horde. It should at least work with Turba2.
# Currently, it does not honor the owner of the addresses stored in the db.
#
# put this into ~/.muttrc:
#      set query_command = "~/bin/query-turba.pl '%s'"
# choose a mysql user and password and at least, via 'mysql':
#      GRANT SELECT ON horde.turba_objects TO <user> IDENTIFIED by <passwd>
# and change the config below as desired.
#
# for mor information, see:
#      <http://www.mutt.org/>
#      <http://www.horde.org/apps/turba>
#
#
#
# Copyright 2012 by Knut Esztermann <knut@esztermann.de>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


use strict;
use warnings;
use DBI;

# ---------- config options ----------
# Database connection data - change as needed
my $host = "localhost";             # on which machine does the horde db live?
my $database = "horde";             # this is the default db name
my $user = "user";                  # mysql <user> as chosen by you
my $password = "passwd";            # mysql <passwd>
my $extrainfo = "object_alias";     # what information to put in the 3rd column
# ---------- config ends ----------

# set search word from command line
my $search = join(" ", @ARGV)."%";

eval {

# open db
my $dsn = "DBI:mysql:database=$database;host=$host";
my $dbh = DBI->connect($dsn, $user, $password, {PrintError => 0, RaiseError => 0})
        or die "Could not connect to database $database\@$host: $DBI::errstr\n";

$search = $dbh->quote($search);

# This default query looks for the search word in firstname and lastname
# but returns only records containing an email address.
#
# If you would like to change the query please note that the query
# should return, in this order: email, complete name, extra information.
my $query = sprintf("SELECT object_email, CONCAT_WS(\" \", object_nameprefix, object_firstname, object_middlenames, object_lastname, object_namesuffix), %s FROM turba_objects WHERE (object_firstname LIKE %s OR object_lastname LIKE %s) AND LENGTH(object_email)", $extrainfo, $search, $search);

my $sth = $dbh->prepare($query)
        or die "Could not prepare query: $DBI::errstr\n";

$sth->execute
        or die "Could not query database $database\@$host: $DBI::errstr\n";

my $rows = $sth->rows;
print "Found $rows results matching $search\n";

while (my $ref = $sth->fetchrow_arrayref) {
        my $email = $$ref[0];
        $email = "" if !$email;

        my $name = $$ref[1];
        $name = "" if !$name;
        $name =~ s/^ +//;       # trim left
        $name =~ s/ +$//;       # trim right
        $name =~ s/  +/ /;      # eliminate double spaces resulting from
                                #  non-null empty fields
        my $alias = $$ref[2];
        $alias = "" if !$alias;

        print $email."\t".$name."\t".$alias."\n";
}

$sth->finish;
$dbh->disconnect;

exit 1 if !$rows;           # non-zero result code if no entries were found

};                          # error handling
print $@;
exit -1;