blog · git · desktop · images · contact & privacy · gopher


Geekiges Mail-Setup für Arch

Man sollte meinen, dass es "Anleitungen" wie die folgende wie Sand am Meer gibt. Ist aber nicht so, manchmal überwiegt eben "RTFM". :D Im Nachhinein war es ja auch nicht schwer und ich erzähle hier sicher nur Einsteigern etwas neues ;) ... die Informationsfindung ist immer so eine Sache, wenn man unter Umständen nicht genau weiß, nach welchen Begriffen zu suchen ist.

Es soll hier um die Einrichtung von mutt-ng als Mail-Client gehen. Abgeholt werden die Mails von der klassischen fetchmail/procmail-Kombination und dann in Maildirs gestopft. Versand läuft über das kleine Programm msmtp, welches vorallem mehrere Accounts unterstützt und somit die Unterscheidung vornimmt, über welchen externen Mailserver nun welche Mail geschickt werden soll.

Sinn des ganzen soll neben dem Erfahrungswert auch sein, dass ich nicht ins X muss, nur um Mails zu checken. Es sind so viele Dinge auch ohne GUI möglich - bis auf mein bisheriges Mail-Verhalten, das konsequent auf Thunderbird gesetzt hat. ;)

Fangen wir an:

Das alte mbox-Format erscheint mir ein bisschen zäh und "outdated", daher setze ich hier auf's Maildir-Format. Unsere Mails werden in ~/Mail liegen, dort drinnen befinden sich dann aber erst die eigentlichen Mails nach Accounts aufgeteilt (Uni, Privat, ...). Daher wäre der erste Schritt also, ~/Mail anzulegen. ;)

fetchmail

Fetchmail wird komplett über die Datei ~/.fetchmailrc eingerichtet (so, wie auch die folgenden Programme nur über eine Datei konfiguriert werden). Kommentiertes Beispiel:

# Erstmal ein paar Defaults setzen, die für alle Accounts gelten - procmail wird global als MDA gesetzt
defaults proto pop3 uidl
    keep
    mda "/usr/bin/procmail"

# dieser Account nutzt im Idealfall TLS:
poll mail.account-eins.de
    user erster there with pass omg is nobody here

# nutzt SSL ohne Zertifikats-Check:
poll pop.account-zwei.de
    user nocheiner there with password uffgeheim is nobody here ssl sslfingerprint "10:01:10:01:10:01"

Die Syntax mutet ein wenig gekünstelt umgangssprachlich an, aber was soll's. Wir haben also zwei Accounts definiert auf zwei unterschiedlichen Servern. Fetchmail nutzt immer die höchstmögliche Verschlüsselung, das heißt, man landet bei TLS-Servern automatisch im TLS - praktisch.

Das "keep" bedeutet übrigens, dass alle Mails auf dem Server belassen werden. Gerade für's Testen unerlässlich.

"user" und "pass" geben natürlich die Zugangsdaten auf dem externen Server an. "is nobody here" wird angegeben, weil sich fetchmail auch ohnehin nicht um die Auslieferung kümmert, sondern procmail.

Bei SSL wird's etwas nervig. Ich habe hier auf einen Zertifikats-Check verzichtet, was natürlich nicht nett ist. Hier wird zum Beispiel erklärt, wie man es richtig machen würde:

http://bronski.net/data/fetchmail-deu.php

Der Fingerprint des Zertifikats wird jedoch trotzdem immer gegengeprüft. Wie kommt man an diesen? Nun, erstmal die ganzen SSL-Geschichten aus der Datei rauslassen und "fetchmail -v" aufrufen. Dort wird er dann stehen. Ist aber auch unter obigem Link erklärt.

Es empfiehlt sich natürlich, da hier die Passwörter im Klartext in der Datei stehen, diese nur für den Besitzer lesbar zu machen. Immerhin etwas.

Es ist ganz nett, fetchmail als Daemon ständig laufen zu haben. Da es sich selbst darum kümmert, dass es nur ein einziges Mal pro User läuft, kann man es einfach in die ~/.bashrc eintragen:

fetchmail -d 300 >/dev/null 2>&1

Somit wird alle 300 Sekunden = 5 Minuten auf neue Mails gecheckt. Die Umleitung hinten lässt nur fetchmails Warnung verschwinden, weil es ja bereits läuft.

Ohne procmail geht die Auslieferung natürlich schief, also ...

procmail

Procmail arbeitet eigentlich nur auf der Basis von regulären Ausdrücken - wenn etwas zutrifft, dann wird die definierte Aktion mit der Mail ausgeführt. Im einfachsten Falle wird sie nur in ihre Ziel-Mailbox geschoben, aber hier wäre zum Beispiel auch der Ansatzpunkt für einen Filter wie Spamassassin.

Beispiel:

# Für den Anfang wollen wir alle Informationen sehen:
VERBOSE=on

# Wo ist das "Grund"-Maildir?
MAILDIR=$HOME/Mail/

# Wo sollen Mails hin, die nicht einsortiert werden konnten?
DEFAULT=$HOME/Mail/.invalid/

# Settings für procmail
PMDIR=$HOME/.procmail/
LOGFILE=$HOME/.procmail/log

# Alle Mails an *@account-eins.de kommen in das Verzeichnis $MAILDIR/.eins/
:0
* ^To:.*@accont-eins.de
.eins/

# Analog mit allen Mails an *@account-zwei.de
:0
* ^To:.*@account-zwei.de
.zwei/

Hier sind ein paar Dinge zu beachten:

Wie man sieht, landen die nicht einsortierbaren Mails dann in der Mailbox ".invalid/". Das ist sinnvoll, um bei Fehlern nicht gleich Mails zu verlieren. Außerdem steht in der Logfile alles wichtige, was natürlich später ausgeschaltet werden kann.

Procmail erstellt übrigens die Maildirs selbst (bis auf das Grundverzeichnis), falls diese noch nicht existieren.

Also nochmal am Beispiel "account-eins": Kommt innerhalb des Headers (das ist die Default-Einstellung, man könnte es auch auf die gesamte Mail ausdehnen) eine Zeile vor, die mit "To:" beginnt, gefolgt von ein paar beliebigen Buchstaben und dann einem "@account-eins.de", so wird die Mail nach ".eins/" einsortiert. Genauer gesagt natürlich dort in das "new"-Unterverzeichnis.

Hier könnte man auch direkt Mails an bestimmte Adressen, von bestimmten Absendern oder mit bestimmten anderen beliebigen darin vorkommenden Strings direkt nach /dev/null befördern.

msmtp

msmtp ist ein sehr schickes kleines Programm, was ich überhaupt noch nicht kannte. Es ist in der Parameter-Syntax und den Return-Values kompatibel zu sendmail, kann also ohne Bedenken statt diesem eingesetzt werden. Der attraktivste Punkt des Programms: Je nach "From:" im Header der Mail wird diese über einen anderen SMTP-Server verschickt! Damit kriegt man auch einfache Art und Weise multiple Accounts geschenkt - auch, wenn der Mailclient selbst das nicht kann. :)

Die Konfiguration ist hier ganz einfach:

# der erste Account, TLS und Auth soll genutzt werden
account eins
tls on
tls_certcheck off
auth on
host mail.account-eins.de
from ich@account-eins.de
user usernameamserver
password wiederstrenggeheim

# und ganz analog ein zweiter account:
account zwei
tls on
tls_certcheck off
auth on
host mail.account-zwei.de
from uiuiui@account-zwei.de
user samson@account-zwei.de
password lilooooo

# default account:
account default : zwei

Wie man sieht, wird mit "tls on" die Verschlüsselung angefordert, aber ohne Zertifikatscheck - wie man das sauber löst, ist einer Suchmaschine zu entnehmen.

Das war's auch schon. Jenachdem, ob eben "ich@account-eins.de" oder "uiuiui@account-zwei.de" der Absender ist, wird der entsprechende Server gewählt.

mutt-ng

Mutt kam mir beim ersten Blick zwar etwas ätzend vor, aber es kommt tatsächlich mit ganz sinnvollen Voreinstellungen daher. Außerdem verwende ich hier mutt-ng, was schonmal eine nette Sidebar mit einer Übersicht der vorhandenen Mailboxen mitbringt. Ferner ist die Verwendung von Maildirs bei diesem Programm recht einfach.

Die folgende Beispiel-Config sieht auf den ersten Blick natürlich etwas länglich aus, aber das meiste kommt wirklich durch die Sidebar bzw. die Hotkeys dafür. Zugegebenermaßen ist vieles aus den unten genannten Quellen übernommen. ;)

Beispiel:

###################################
# Grundlegendes Setup für Maildirs:

# Typ setzen
set mbox_type=Maildir

# Wo landen geschrieben Mails?
set record="+.Sent"

# Diese Mailboxen gibt es - find listet sie alle für uns auf,
# dafür der führende Punkt in den Maildir-Namen. Natürlich hätte man sie
# auch manuell hier auflisten können, aber so spart man sich späteres
# editieren dieser Datei.
mailboxes `find ~/Mail -maxdepth 1 -type d -name ".*" -printf "+'%f' "`


############
# für mSMTP:

set sendmail="/usr/bin/msmtp" 
set envelope_from=yes

# Wir wollen die Header im Editor dann auch
# nochmal editieren können:
set edit_headers=yes
set editor="vim -c 'set textwidth=72' +"

# Mit diesen Macro's kann mal eben der Absender verändert werden
macro generic "<esc>1" ":set from=ich@account-eins.de" 
macro generic "<esc>2" ":set from=uiuiui@account-zwei.de"


##################################################
# Auswahl der zu lesenden Mailbox und die Sidebar:

macro index c "<change-folder>?<toggle-mailboxes>" "open a different folder"
macro pager c "<change-folder>?<toggle-mailboxes>" "open a different folder"

# Sidebar im Index und Pager einblenden mit b
macro index b ':toggle sidebar_visible^M'
macro pager b ':toggle sidebar_visible^M'

# Sidebar Properties
set sidebar_width=25
set sidebar_visible

# Ctrl+P, geht zur vorherigen/oberen Mailbox in der Sidebar
bind index \CP sidebar-prev
# Ctrl+N, geht zur nächsten/unteren Mailbox in der Sidebar
bind index \CN sidebar-next
# Ctrl+O, öffnet die in der Sidebar ausgewählte Mailbox
bind index \CO sidebar-open

# Ctrl+P, geht zur vorherigen/oberen Mailbox in der Sidebar
bind pager \CP sidebar-prev
# Ctrl+N, geht zur nächsten/unteren Mailbox in der Sidebar
bind pager \CN sidebar-next
# Ctrl+O, öffnet die in der Sidebar ausgewählte Mailbox
bind pager \CO sidebar-open

# Mailboxen mit neuen Nachrichten in der Sidebar rot kennzeichen
color sidebar_new brightred default


# Bissele bunt und sonstiges:
color header brightgreen black ^From:
color header brightgreen black ^Subject:
color header brightcyan black ^To:
color header brightcyan black ^Cc:

set include=ask-yes # ask whether to cite a mail when replying

That's it! :)

Benachrichtigung an der Shell

Vielleicht hätte man gerne bei neuen Mails so ein "You have mail" an der Console. Das "comsat", was procmail ansprechen will, geht wohl ins Leere. Bash bringt auch eine "MAILCHECK"-Funktion mit, die aber nicht toll funktioniert. Mir gefällt diese Idee hier schon besser:

http://kikhome.net/?p=11

Ich habe das Script aber etwas anders realisiert. Bei mir sieht es so aus:

#!/bin/bash

# Prüft, ob die new/ Verzeichnisse im Maildir
# neuer sind als ihre Cache-Files. Letztere
# müssen aber bereits existieren bzw. es wird
# nur für die existierenden Cache-Files geprüft.
# So kann man z.B. das .Sent-Verzeichnis auslassen.

# Die Cache-Files haben also die Gestalt:
# $MAILDIR/cache.account-eins
# $MAILDIR/cache.account-zwei
# usw.

MAILDIR=$HOME/Mail
typeset -i had=0

if [[ -d $MAILDIR ]]; then
    # Schau dir alle Cache-Files an:
    for file in $MAILDIR/cache.*; do

        # Entfernt links das größte passende
        # bis inkl. "cache", was dann das
        # Dir für diese Mailbox ergibt.
        thisdir=$MAILDIR/${file##*cache}/new

        # War die letzte Änderung in diesem
        # Verzeichnis nach dem letzten touch?
        if [[ $thisdir -nt $file ]]; then

            # Sie war! Also gib 'ne Meldung.
            echo "New mail: ${file##*cache.}"
            touch $file
            let "had += 1"
        fi
    done
fi

# Falls eine Nachricht ausgegeben wurde, schieb' noch was hinterher.
# Das hat folgenden Grund: Dieses Script ist dazu gedacht, bei
# jedem Prompt mittels Command-Substitution aufgerufen zu werden.
# Diese frisst aber trailing newlines auf, das letzte newline würde
# also fehlen. Schiebt man noch ein \r hinterher, passt es ...
# Das soll aber eben nur gemacht werden, wenn auch neue Mails da sind.
if [ $had -gt 0 ]; then
    echo -ne "\r"
fi

Nun den Bash-Prompt z.B. in der ~/.bashrc so modifizieren, dass dieses Script bei jeder neuen Zeile aufgerufen wird:

PS1='$(~/bin/newmail.sh)\[\033[32m\]<$(date +%H:%M)>\[\033[0m\] \[\033[01;33m\]\w\[\033[0m\] \$ '

Würde man das so verwenden, kriegt man aber auch jedesmal, wenn man mutt beendet hat, eine angebliche Nachricht über neue Mails. Das liegt daran, dass mutt die Mails vom new/ ins cur/ verschiebt und dabei wird die Zeit von new/ neu gesetzt. Abhilfe schafft folgender Alias:

alias mutt='mutt && touch ~/Mail/cache.*'

Nach mutt werden also die Cache-Files neu getoucht, womit sie definitiv neuer sind und dadurch nicht triggern.

Quellen