Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen gezeigt.

Link zu dieser Vergleichsansicht

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).