====== Linux: Scan2Fileserver-Gateway mit einem Multifunktionsdrucker und Postfix ====== Multifunktionsgeräte mit Scan- und Druckfunktion gibt es mittlerweile zu Hauf. Allerdings ist eine anständige Linux-Treiberunterstützung immer noch Mangelware. Also greift man am besten zu einem Gerät, welches Postscript als Druckersprache unterstützt. Wie aber nutzt man die Scanfunktion, wenn keine Treiber verfügbar sind?\\ Wenn das Gerät **//scan2mail//** unterstützt (d. h. gescannte Dokumente als PDF oder Jpeg per Mail verschickt), kann man sich mit Postfix eine recht elegante Lösung basteln. ====== Ausgangssituation ====== Ich verwende als Multifunktionsdrucker einen [[http://www.oki.de/fcgi-bin/public.fcgi?pid=97&cid=126&prid=594&pdflag=1|OKI C5550 MFP]], der sich einerseits durch eine große Funktionsvielfalt auszeichnet (Ethernet-Anschluss, Vorlageneinzug, optionale Duplexeinheit, Farbdrucker und -scanner, Scan2Mail), jedoch andererseits keinerlei Linux-Unterstützung seitens des Herstellers erfährt. Da es sich um einen Postscript-Drucker handelt, ist das Fehlen eines Linux-Treibers nicht so tragisch.\\ Die Scan-Einheit wird weder von [[http://www.sane-project.org|Sane]] noch von den sonstigen üblichen Verdächtigen unterstützt, beherrscht jedoch Scan2Mail. Deshalb kann man das Gerät mit der Hilfe von Postfix und einem Bash-Skript zu einem recht komfortablen Netzwerkscanner aufrüsten.\\ \\ Das soll folgendermaßen ablaufen:\\ \\ {{virtual:blog:scan2mail1.png?nolink|Ablauf Scannen}}\\ ====== Drucker/Scanner ====== Der Drucker/Scanner muss wissen, wohin er die gescannten Dokumente schicken soll. Dafür trägt man (irgendwo in der Gerätekonfiguration) die Adresse des Servers ein, auf dem Postfix läuft (siehe nächster Punkt). ====== Postfix ====== Eine E-Mail ist - grob vereinfacht - eine [[http://tools.ietf.org/html/rfc2822|Textdatei]], die man im Klartext lesen kann. Sie besteht aus einem Kopfteil mit Betreff, Sender- und Absenderadresse sowie einem Hauptteil mit der eigentlichen Nachricht. Auch Binäranhänge wie PDF-Dokumente oder Bilder werden in Blöcke von ASCII-Zeichen übersetzt und sind im Hauptteil enthalten.\\ \\ Zunächst muss Postfix so konfiguriert werden, dass es E-Mails an eine bestimmte Adresse nicht an ein Postfach ausliefert, sondern an ein (noch zu behandelndes) Bash-Skript übergibt. Eine [[http://www.linuxnetmag.com/de/issue8/m8hylafax1.html|Anleitung]] hierzu ist (in anderem Zusammenhang) in einem Artikel des [[http://www.linuxnetmag.com|Linux NetMags]] zu finden (Punkt 6.11).\\ \\ Zunächst muss ein sogenannter Transport definiert werden. Dabei wird Postfix mitgeteilt, dass E-Mails an eine bestimmte Subdomain besonders zu behandeln sind.\\ \\ Da mein DruckScanner über eine Zahlentastatur verfügt, wähle ich **90** als Subdomain, weil sich das einfach eintippen lässt. Alle E-Mails, die ich an die Adresse //irgendwas@**90**.meinserver// sende, sollen an mein Bash-Skript (siehe unten) weiter gereicht werden. "irgendwas" und ".meinserver" kann man auch weglassen, das heißt, ich muss auf der Zahlentastatur nur //@90// eingeben.\\ \\ Das Folgende muss in die Datei **///etc/postfix/transport//** eingefügt werden: # muss durch den Hostnamen des Servers ersetzt werden 90. mailfile:localhost Damit wird bestimmt, dass alle Mails an die Subdomain "90" an den Transport "mailfile" übergeben werden. Die Konfigurationsdatei muss mittels dem Befehl postmap /etc/postfix/transport in ein für Postfix lesbares Format umgewandelt werden und es muss geprüft werden, ob in der Datei **///etc/postfix/main.cf//** die Zeile transport_maps = hash:/etc/postfix/transport vorhanden ist, damit die Anpassungen auch wirksam werden.\\ \\ Jetzt muss Postfix noch gesagt werden, wie genau es E-Mails mit dem Transport "mailfile" behandeln soll. Hierzu müssen in der Datei **///etc/postfix/master.cf//** die Zeilen mailfile unix - n n - 1 pipe flags= user=scanmail argv=/usr/local/bin/scanmail2file ${recipient} angefügt werden.\\ \\ Damit wird festgelegt, dass E-Mails, die vom Transport "mailfile" behandelt werden, an das Skript **///usr/local/bin/scanmail2file//** übergeben werden. Das Skript wird mit den Rechten des Benutzers "scanmail" ausgeführt. Dieser muss also existieren (oder die Zeile muss angepasst werden).\\ \\ Mit dem Befehl postfix reload werden die Änderungen aktiviert. ====== Skript ====== Postfix bietet Mechanismen, um den Inhalt ein- und ausgehender Mails mittels Filtern zu bearbeiten. Beschrieben ist das unter anderem [[http://www.postfix.org/FILTER_README.html#simple_filter|hier]] auf der [[http://www.postfix.org|Postfix-Webseite]]. Das dort beschriebene Skript habe ich abgewandelt, um es an meine Anforderungen anzupassen. Es sollte unter **///usr/local/bin/scanmail2file//** abgelegt werden (**Achtung: Die Datei muss ausführbar sein!**). Das Skript (und die Beispiel-Konfigurationsdatei) kann auch {{virtual:blog:scanmail.tar.gz|als Archiv}} heruntergeladen werden. #!/bin/sh ##################################################################### # scanmail2file # # Simple shell-based filter. It is meant to be used as postfix mail # # transport and is invoked as follows: # # # # /path/to/script -f ... # # # # Author: yeat (y[]yeat.net) # # # # It takes a message from stdin, extracts all MIME-parts # # (i. e. binary attachments) and saves PS and PDF attachments to # # disk. # ##################################################################### ##################################################################### # Configuration # # adjust variables to your system environment # ##################################################################### #Location of file map INIFILE=/etc/scanmail/scanmail2file #Location of logfile LOGFILE=/var/log/scanmail2file #Location for temporary files TMP_DIR=/tmp ##################################################################### # No user-servicable parts beyond this point... # ##################################################################### RECEIVER=$1 SENDER_NO=$(echo $RECEIVER | sed 's/^.*@\([0-9]*\)\..*$/\1/') EX_TEMPFAIL=75 # Clean up when done or when aborting. trap "cd ..; rm -rf mailfax.$$" 0 1 2 3 15 # Check for scan map [ -f $INIFILE ] || { echo $INIFILE does not exist; exit $EX_TEMPFAIL; } # Start processing. cd $TMP_DIR || { echo $INSPECT_DIR does not exist; exit $EX_TEMPFAIL; } mkdir mailfile.$$ cd mailfile.$$ cat >in.$$ || { echo Cannot save mail to file; exit $EX_TEMPFAIL; } grep $SENDER_NO $INIFILE | while read PREF DESTINATION PERM; do #write all attachments to temporary files cat in.$$ | METAMAIL_TMPDIR=. metamail -d -w -q -r #copy all PDF, PS, TIF and JPG files to destination for fn in $(ls -tr *.[pP][dD][fF] *.[pP][sS] *.[tT][iI][fF] *.[jJ][pP][gG] 2>/dev/null); do #filename DEST_FN="$DESTINATION/$(date +%Y%m%d%H%M%N)$(echo $fn | sed -e 's/.*\(\..*\)$/\1/')" #copy cp "$fn" "$DEST_FN" #file permissions chmod $PERM "$DEST_FN" done done exit $? Der Ort für die Ablage der Dateien wird in der Konfigurationsdatei **///etc/scanmail/scanmail2file//** festgelegt. In der hier besprochenen Konstellation sieht sie folgendermaßen aus: ############################################################################# #sender-id destination permission ############################################################################# 90 /media/data/scanner 660 Die erste Spalte gibt die Subdomain an, die zweite Spalte definiert das Zielverzeichnis für die gescannten Dateien (**Achtung: Der in der Datei master.cf angegebene Benutzer muss Schreibrechte auf das Verzeichnis besitzen!**). In der dritten Spalte werden die [[wpde>chmod|Zugriffsrechte]] zugewiesen.\\ \\ Wenn Postfix eine E-Mail an das Skript übergibt, dann passiert Folgendes: * in /tmp ($TMP_DIR) wird ein temporäres Unterverzeichnis angelegt (mailfile.$$) und dort hin gewechselt * die E-Mail wird in die Datei **//in.$$//** geschrieben * die Dateianhänge der E-Mail werden mittels [[http://rand-mh.sourceforge.net/book/overall/metama.html|metamail]] extrahiert und gespeichert * die extrahierten Dateien werden in das entsprechende Zielverzeichnis kopiert, als Dateiname wird ein Zeitstempel verwendet * die Zugriffsberechtigungen werden gesetzt * das temporäre Verzeichnis wird beim Beenden des Skripts (auch bei fehlerbedingtem Abbruch) gelöscht Es ist übrigens möglich, mehrere Scan-Ziele als Postfix-Transport und in /etc/scanmail/scanmail2file zu definieren. ====== Cronjob ====== Da ich nicht möchte, dass die Festplatte im Server nach und nach mit gescannten Dateien zugemüllt wird, erstelle ich einen [[wpde>cronjob|Cronjob]], der die Dateien nach einer festgelegten Zeit wieder löscht. Dazu wird die Datei **///etc/crontab//** um die Zeile 25 * * * * root /usr/bin/find /media/data/scanner/ -mmin +60 -type f -exec rm {} \; &>/dev/null erweitert. Damit wird dem Cron-Dämon folgendes mitgeteilt:\\ **//Suche 25 Minuten nach jeder vollen Stunde im Verzeichnis /media/data/scanner nach Dateien, die älter sind als 60 Minuten und lösche diese.//**\\ Die von mir verwendeten Zeiten können natürlich nach Belieben angepasst werden (Angabe "**25** * * * *" ganz am Anfang sowie "-mmin +**60**" in der Mitte).