Hier werden die Unterschiede zwischen zwei Versionen gezeigt.
virtual:blog:scan2fileserver-gateway_mit_einem_multifunktionsdrucker_und_postfix [2017/10/23 15:45] |
virtual:blog:scan2fileserver-gateway_mit_einem_multifunktionsdrucker_und_postfix [2017/10/23 15:45] (aktuell) |
||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ====== 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: | ||
+ | # <meinserver> muss durch den Hostnamen des Servers ersetzt werden | ||
+ | 90.<meinserver> 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 <recipient>... # | ||
+ | # # | ||
+ | # 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). |