Schlagwort-Archive: Maildrop

maildrop-Fallstricke und was man dagegen tun kann

Wenn maildrop-Filter mit der Zeit wachsen und komplexer werden steigt das Risiko, dass sich irgendwo ein Fehler einschleicht. Da die Debugging und Fehlererkennungsmechanismen von maildrop eher rudimentär ausfallen – besonders bei verteilten Filtern in mehreren Dateien – kann ein solcher Fehler schnell zum Verlust von E-Mails führen.

Probleme mit den Dateirechten

maildrop ist sehr empfindlich was die Dateirechte der Hauptfilterdatei (~/.mailfilter) angeht. Sind diese nicht auf 0600 gesetzt, verweigert maildrop jeglichen Dienst. Da ich meine Filter über git versioniere und git Dateirechte schlicht aus der umask generiert (Ausnahme ist das +x-Flag) kam es hier gelegentlich zu Problemen.

Die Lösung ist so einfach wie wirkungsvoll. Über die .qmail-Datei rufe ich ein Wrapper-Script maildrop-wrapper.sh auf, welches die Übergabe an maildrop versucht. Sollte ein Fehler auftreten, wird versucht die Rechte zu korrigieren und anschließend ein weiterer Versuch gestartet.

[shell]
#!/bin/bash
#
# maildrop-wrapper.sh

maildrop ~/.mailfilter

if [ $? -ne 0 ]; then
# Try to correct file permissions and retry
chmod 0600 ~/.mailfilter
maildrop ~/.mailfilter
fi
[/shell]

Der Vollständigkeit halber hier auch die entsprechende .qmail-Datei:

[generic]
# .qmail
# Deliver email via maildrop-wrapper.sh
|~/bin/maildrop-wrapper.sh
[/generic]

Fehler im Filter

Um bei Fehlern im Filtercode dennoch zumindest eine Zustellung zu ermöglichen, habe ich eine grundlegende Filterkonfiguration in die ~/.mailfilter gepackt. Daher sollte es an dieser eigentlich keine Änderungen geben, die Fehler verursachen können.

[generic]
# mailfilter
# Maildrop filter
#
# This file is just for data integrity, it includes the
# actual mailfilter in file „main“
# If any exception occurs while executing main, this file
# makes sure that the affected mail is not dropped

# DO NOT ADD ANY ADDIDTIONAL CODE OUTSIDE THE EXCEPTION SCOPE
# Catch exceptions in actual filter
exception {

# Include the actual filter
CONFIG_DIR=“$HOME/etc/maildrop“
include „$CONFIG_DIR/main“

# If anything worked until now, exiting with success
# is quite fine
EXITCODE=0
exit
}
# DO NOT ADD ANY ADDIDTIONAL CODE OUTSIDE THE EXCEPTION SCOPE

# If anything goes wrong, deliver mail to Maildir
to „$HOME/Maildir“
[/generic]

Der simple aber wirkungsvolle Gedanke dahinter – packe alles was irgendwie kritisch werden könnte in einen exception-Block, der alle möglichen Fehler auffängt. Wird die E-Mail innerhalb dieses Blocks zugestellt, passiert nichts mehr. Kann jedoch nicht zugestellt werden, wird die E-Mail in (fast) jedem Fall ins Standard-Maildir ~/Maildir zugestellt.

Blacklist für maildrop halbautomatisch erstellen

Auf meinem Uberspace nutze ich eine Kombination aus maildrop und Spamassassin um nervigem Spam schnell und ohne manuelles Eingreifen aus dem Verkehr zuziehen. Manchmal kommt es jedoch vor, dass eine E-Mail nicht als Spam erkannt wird oder – ebenfalls blöd – erwünschte Mails herausgefischt werden.

Mein Setup sieht vor das Mails zunächst gegen eine Whitelist geprüft werden, anschliesend folgt eine Blacklist und zuletzt, wenn weder Whitelist noch Blacklist angeschlagen haben folgt der Spamassassin. Wenn jetzt eine E-Mail von einem Spamabsender doch mal durchkommt habe ich bisher über SSH die Blacklist angepasst. Diese ist mittels der lookup-Funktion von maildrop angebunden.
Diesen Vorgang wollte ich nun Vereinfachen und habe ein kleines Script geschrieben, welches ein bestimmtes Verzeichnis im Maildir einliest und alle Mailadressen im ersten From-Header Zeilenweise in eine Blacklist schreibt. Die Einträge werden alphabetisch Sortiert und Dubletten entfernt.
So muss dann die entsprechende E-Mail nur noch in das Verzeichnis verschoben oder kopiert werden, um einen Blacklist-Eintrag zu erhalten.
Dieses Script, das nebenbei nach dem gleichen Muster auch eine Whitelist erstellt (falls der Spamassassin mal zu übereifrig ist), lasse ich mittels Runwhen einmal täglich ausführen. Nach der dem Durchlauf des Scripts können die Mails dann wieder aus dem Verzeichnis entfernt werden, die Einträge bleiben dabei natürlich erhalten.

Konfigurieren muss man bei Verwendung des Scripts die Variablen OUTPUT und INPUT:

  • OUTPUT – Hier gehört das Verzeichnis hinein wohin das Script die Listen schreiben soll, natürlich muss dieses Beschreibbar sein
  • INPUT – Diese Variable wird erst für den Durchlauf der Blacklist konfiguriert, hier gehört der Pfad zum Blacklist-Maildir hin
  • INPUT –Beim zweiten mal für den Durchlauf der Whitelist gehört der Pfad zum Whitelist-Maildir hin

Hier noch das gesamte Script:

[shell]
#!/bin/bash
#
# autolister.sh
#
# Automatic generation of e-mail black- and whitelists for maildrop from mails in specific (IMAP-)folders by „From“-header
#
# For more information see (German)
#
# Copyright 2014, GOLDERWEB – Jonathan Golder
#
# 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
#

function auto_list(){
# Make sure OUTPUT and INPUT are directories
if [[ ! -d $OUTPUT || ! -d $INPUT ]]
then
echo ‚ERROR: OUTPUT and INPUT must be directories!‘
exit 1
fi

# Warn if other list then black or white
if [[ $1 != ‚black‘ && $1 != ‚white‘ ]]
then
echo „WARNING: $1 normaly need to be ‚black‘ or ‚white'“
fi

# Create empty list if there is none before to prevent errors
if [[ ! -f $OUTPUT/${1}list-auto ]]
then
touch $OUTPUT/${1}list-auto
fi

# Make a copy of current list
cp $OUTPUT/${1}list-auto $OUTPUT/.${1}list-auto.bak

# Grep all „From“-headers width mailadresses from mails in $INPUT and write to $OUTPUT/.raw.tmp
grep -rEo -m 1 „^From: .*\@.*$“ $INPUT/* >$OUTPUT/.raw.tmp

# Grep email adresses and write to $OUTPUT/.done.tmp
grep -oE ‚[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+‘ $OUTPUT/.raw.tmp >$OUTPUT/.done.tmp

# Concatenate old and new list, sort alphabetically ascending and unique entries
cat $OUTPUT/.${1}list-auto.bak $OUTPUT/.done.tmp | sort | uniq -i >$OUTPUT/${1}list-auto

# Remove temporary files
rm $OUTPUT/.raw.tmp
rm $OUTPUT/.done.tmp
rm $OUTPUT/.${1}list-auto.bak
}

# Configure OUTPUT for both black and whitelist
OUTPUT=$HOME/etc/maildrop

#Configure INPUT for blacklist and create it
INPUT=$HOME/users/golderweb/.Spam.Blacklist
auto_list ‚black‘

#Configure INPUT for whitelist and create it
INPUT=$HOME/users/golderweb/.Spam.Whitelist
auto_list ‚white‘
[/shell]

Weitere Informationen zu maildrop und zur Einrichtung eines runwhen-Dienstes finden sich im Wiki der Ubernauten.

Update

Jetzt auch als Gist auf GitHub unter https://gist.github.com/golderweb/e02d405699588af09383 verfügbar, zum einfachen klonen oder forken.