Impostazione di un servizio Fax in spedizione e ricezione con Linux Indice Introduzione... 2 Piattaforma Utilizzata... 2 Applicativi richiesti... 2 Procedura per l invio di fax... 2 FAX-NR:numero_destinatario... 6 Procedura per la ricezione di fax... 6 Note finali... 10
Introduzione L obiettivo di questo documento consiste nell utilizzare strumenti GPL/OpenSource per poter realizzare un sistema di faxing robusto ed efficace ma allo stesso tempo semplice. Lo scopo principale era quello di poter inviare e ricevere fax dalla rete in ambiente intranet, direttamente dai documenti prodotti ad esempio con Word Processor, attraverso un fax gateway dotato di un semplice modem analogico. Piattaforma Utilizzata Linux Slackware 8.1 versione Kernel 2.4.18 Il modem utilizzato è stato un vecchio US Robotics Sportster 33.600 a cui abbiamo abilitato l Auto Answering. Applicativi richiesti Lato server Mgetty Samba faxspool (per lo spooling dei fax) faxsend (per l invio dei fax) faxrunq (per il passaggio dei fax dalla coda a faxsend) Script: newfax (per la ricezione) e faxfilter (per l invio) Questi script vengono forniti già con mgetty ma in questo articolo ne verranno presentate due versioni modificate ed adattate a specifiche esigenze Lato client Una qualsiasi stampante postscript (ad esempio Apple Laser Writer) Procedura per l invio di fax Per prima cosa occorre avere un modem analogico collegato ad una seriale ed identificare quale, nel mio caso ttys0. Dopo aver compilato mgetty seguendo le semplici istruzioni cp policy.h-dist policy.h Make && make install Occorre configurare l mgetty.config impostando # livello di debug debug 4 # fax station id fax-id 390114023455 # la velocità in bps per i modem(s) speed 56000 #la porta a cui è collegato il modem port ttys0 speed 56000 A questo punto occorre utilizzare il faxfilter opportunamente modificato quello fornito da mgetty è in tedesco e probabilmente va adattato ad esigenze specifiche.
Questo è quello che ho utilizzato (adattato da massimo Nuvoli massimo@nuvoli.to.it) #!/usr/bin/perl ######################################################################### ## $MAILER="/bin/mailx"; $FAXFILE="/tmp/fax/tmp_faxlp.$$"; $Username=""; $Filename=""; $Username=$ARGV[0]; $Filename=$ARGV[1]; if (($Username eq "nobody") ($Username eq '')) $Mailname="postmaster"; else $Mailname=$Username; open OU,">$FAXFILE"; open (IN,$Filename); $ns=0; while (<IN>) if (/fax-nr\s*\:\s*(\d+)/i) $numero=$1; $ns=1; print OU $_; close (OU); if (!$ns) open OU," $MAILER -s \"Problemi con la spedizione del fax\" $Mailname"; print OU "Numero non specificato nel documento (fax-nr?)\n"; close OU; # unlink $FAXFILE; exit(-1); else $res=`/usr/local/bin/faxspool -u $Username -f $Username $numero $FAXFILE 2>&1`; open OU," $MAILER -s \"Esito accodamento fax\" $Mailname"; print OU "Questo <E8> l'esito dell'avvenuto accodamento\n"; print OU $res; close OU; # unlink $FAXFILE; exit(0); Questo file va depositato nella directory /etc. A questo punto occorre condividere una risorsa FAX via samba che sia stampabile e per questo aggiungere nel vostro smb.conf [fax]
comment = Fax in rete path = /tmp/fax force user = root valid users = paolo printable = Yes print command = /etc/faxfilter %u %s lpq command = /bin/ls /var/spool/fax/outgoing * il force user è necessario per poter utilizzare correttamente faxspool ** per evitare problemi di accesso utilizzate un utente di accesso alla rete che sia anche un utente del server linux e possibilmente quello specificato dal parametro valid users *** riavviare samba dopo le modifiche In caso di corretto accodamento il faxfilter invia una conferma all utente che ha inviato il fax con un messaggio di questo tipo: Subject: Esito accodamento Questo è l'esito dell'avvenuto accodamento spooling to /var/spool/fax/outgoing/f000004... spooling /tmp/fax/tmp_faxlp.31386... /tmp/fax/tmp_faxlp.31386 is format: ps %%[ Page: 1 ]%% %%[ LastPage ]%% \nputting Header lines on top of pages... \nfax queued successfully. Will be sent at next ``faxrunq'' run.\n
Installazione della stampante/fax postscript su ogni client che vuole faxare: a questo punto accedere via rete al server linux e fare un doppio clic sulla risorsa fax che dovrà essere liberamente disponibile se avete effettuato l accesso con uno user autorizzato ed esistente sul server linux. Vi verrà chiesto di installare la risorsa. Basta chiamarla fax ed utilizzare il driver di una stampante laser postscript (nel nostro caso la Apple Laser Writer) per cui è bene avere il CD di installazione di Win98 con i driver necessari. A questo punto occorre solo più configurare sendfax che è il programma che si occupa effettivamente di inviare i fax dopo che questi sono stati accodati da faxspool per l invio nella directory /var/spool/fax/outgoing. Il file di configurazione si trova in /usr/local/etc/mgetty+sendfax e si chiama sendfax.config Occorre specificare in questo file in modo particolare il fax device # which devices to use for outgoing faxes fax-devices ttys0 e l ID intestazione del nostro fax # which fax number to transmit to the receiving station fax-id 39 011 4023455 in caso di necessità specificare anche il prefisso per il modem (Tone o Pulse) dial-prefix ATDT La procedura richiede anche che nella directory delle configurazione di mgetty (/usr/local/etc/mgetty+sendfax) siano presenti due file (fax.allow e fax.deny) in cui inserire gli user che possono o non possono utilizzare il sistema. Inoltre per inviare fax corretti dal punto di vista formale è bene modificare il file faxheader è adattarlo alle vostre esigenze FAX FROM: Neltink Sas 39 011 4023455 TO: @T@ PAGE: @P@ OF @M@ Per far si che sendafax si attivi è necessario eseguire il programma faxrunq che si occupa semplicemente di verificare in /var/spool/fax/outgoing la presenza di fax in spool e di inviarli a sendfax che si occuperà della effettiva spedizione. Questo è un esempio dell output prodotto dall esecuzione del comando faxrunq root@fax:/# faxrunq processing F000009/JOB... /usr/local/sbin/sendfax -v 0114023455 f1.g3 Trying fax device '/dev/ttys1'... OK. Dialing 0114023455... OK. sending 'f1.g3'... command exited with status 0 send mail to paolo... Eseguendo il comando faxrunq i fax in coda verranno immediatamente spediti mentre può essere più comodo lasciare attivo il demone faxrunqd che ad intrevalli di tempo prefissati ed
in maniera assolutamente autonoma controlla la coda dei fax e si preoccupa di inoltrarla sendfax per la spedizione. Anche faxrunq ha un file di configurazione chiamato faxrunq.conf ovviamente sotto /usr/local/etc/mgetty+sendfax in cui è necessario specificare almeno un parametro ovvero il device del fax utilizzato dal server: #fax device fax-devices ttys0 Si possono anche modificare alcuni altri parametri come la possibilità di ricevere email in caso di successo o fallimento dell invio del fax: # when a fax has been successfully sent, "n" otherwise... (default "y") success-send-mail y # transmitted at all... (default "y") failure-send-mail y In caso di successo l utente che ha inviato il fax riceve una email di questo tipo Your fax has been sent successfully at: Thu Sep 12 10:50:58 2002 Subject:OK: your Fax to 01145. Job / Log file: phone 0114023455 user root input /tmp/fax/tmp_faxlp.31188 pages f1.g3 Status Thu Sep 12 10:50:58 2002 successfully sent Sending succeeded after 0 unsuccessful attempts A questo punto siamo pronti per poter inviare il fax dal nostro Word Processor in cui è necessario specificare un parametro fondamentale ovvero il numero di telefono del destinatario. Per poter inviare il documento via fax basta inserire in testa al documento (come prima riga) l istruzione: FAX-NR:numero_destinatario Utilizzate un font stampante come il courier e stampate sulla stampante postscript che avete chiamato in precedenza FAX. Il fax verrà trattato dal faxfilter ed accodato, riceverete una mail per confermare il buon esito dell accodamento. Dopo pochi secondi (se avete in esecuzione in memoria il demone faxrunqd) il server invierà il fax confermando l esito positivo o negativo con una mail. Procedura per la ricezione di fax La procedura che vogliamo attivare è quella che ci consente di ricevere ed accodare i fax è poterli leggere via web, magari organizzandoli e gestendoli con un piccolo applicativo in php. Per fare ciò occorre installare mgetty e specificare nel file /etc/inittab la riga che indica a mgetty di rispondere alle telefonate entranti sul giusto device: #mgetty per ricezione fax m0:2345:respawn:/usr/local/sbin/mgetty /dev/ttys0
A questo punto occorre utilizzare lo script new_fax che consente di ricevere una mail con indicata la posizione del fax da leggere. Nel nostro caso questo è lo script new_fax da noi utilizzato (modificato da Massimo Nuvoli - massimo@nuvoli.to.it) da depositare in /usr/local/lib/mgetty+sendfax #!/usr/bin/perl -w # # Fax filter with more/advanced fetures. # ############ use Mail::Sender; # $DEBUG=1; if ($DEBUG) open OU,">>/tmp/log.faxin"; print OU "--> $$ ($<) ($>)\n"; foreach $el (@ARGV) print OU "ARGV> $el\n"; #$base="/var/spool/fax/archivio/"; $base="/htdir/htdocs_php/fax2/"; $send_via_email=1; $notify_via_email=1; $print_dir=1; #$PREHTML="http://www.in.netlinkl.it/fax/archivio"; $PREHTML="http://php.in.netlink.it/fax2"; $MAILTO="paolo\@in.netlink.it"; $from="fax Server <root\@in.netlink.it>"; $nopt="-s"; $sopt=""; $SENDMAIL = '/usr/lib/sendmail'; $PRINTCMD1 = '/usr/bin/gs -q -spapersize=a4 -sdevice=laserjet -r300 -dnopause -soutputfile=- -- '; $PRINTCMD2 = ' /usr/local/bin/lpr -v -Php3200'; $TMPPRE='/tmp/'; $DPI=300; # risoluzione ps my $hangup_code = shift; my $sender_id = shift; my $number_pages = shift; if ($DEBUG) print OU "code:$hangup_code\n"; print OU "sender:$sender_id\n"; print OU "pagine:$number_pages\n"; print OU "> inizio conversione in ps\n" if($debug); $t=0; foreach $file (@ARGV) $pag[$t]=$file; @partif=split /\//,$file; $ida=$partif[int(@partif)-1]; ($id,$num)=split /\-/,$ida; ($f,$r,$k)=split //,$id; print OU $file," = $r:$f:$k\n" if($debug); system "/usr/local/bin/g32pbm -s <$file >$file.pbm" if ($r eq 'n'); system "/usr/local/bin/g32pbm <$file >$file.pbm" if ($r ne 'n'); system "/usr/bin/pnmtops -noturn -dpi $DPI -width 8.268 -height 11.693 <$file.pbm >$file.ps"; $t++; @parti=split /\//,$pag[0]; $ida=$parti[int(@parti)-1]; ($id,$num)=split /\-/,$ida; print OU "> fine conversione in ps\n" if($debug); $s=0; while($s<$t) $file=$pag[$s]; system "cat $file.ps >>$TMPPRE$$.ps";
$s++; print OU "> fine concatenazione pagine ps\n" if($debug); system "ps2pdf $TMPPRE$$.ps $TMPPRE$$.pdf"; print OU "> fine conversione da ps a pdf\n" if($debug); $sender_id=~s/\s//g; if ($sender_id eq '') $sender_id='non_identificato'; print OU "> invio totale via email\n" if($debug); if ($send_via_email) $sender = new Mail::Sender from => $from; $sender->mailfile ( to => $MAILTO, subject => "Ricevuto fax da $sender_id", msg => "Allegato fax ricevuto", file => "$TMPPRE$$.pdf" ); $filtro='\s,\/,\\\\,\-,\+,\*,\$,\%,\(,\),\='; foreach $fl (split /\,/,$filtro) print OU "Filtro: (",$fl,")\n" if($debug); $sender_id=~s/$fl//g; ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $year+=1900; $mon+=1; $mon=sprintf "%02d",$mon; print OU "> Controllo directory base archivio\n" if($debug); if (not(-e "$base$sender_id")) print OU "> Creazione directory base archivio\n" if($debug); system "mkdir $base$sender_id"; print OU "> Copia del documento in archivio\n" if($debug); system "cat $TMPPRE$$.pdf >$base$sender_id/$id.pdf"; print OU "> Notifica via email con url\n" if($debug); if ($notify_via_email) open (MAIL, " $SENDMAIL $MAILTO"); print MAIL "From: $from\n"; print MAIL "Subject: Ricevuto fax da $sender_id\n"; print MAIL "\n\n"; print MAIL "Per accedere al documento memorizzato:\n"; print MAIL $PREHTML."/$sender_id/$id.pdf\n"; close (MAIL); print OU "> Stampa!!\n" if($debug); if ($print_dir) $cmd= "$PRINTCMD1 $TMPPRE$$.ps $PRINTCMD2"; print OU "> cmd=$cmd\n" if($debug); system($cmd); $exit_value = $? >> 8; print OU "> retval=$exit_value\n" if($debug); print OU "> Rimozione dei temporanei $TMPPRE$$.ps.pdf\n" if($debug); unlink "$TMPPRE$$.ps"; unlink "$TMPPRE$$.pdf"; $s=0; while($s<$t) print OU "> Rimozione dei temporanei $file.tiff.ps\n" if($debug); $file=$pag[$s]; # unlink $file; unlink $file.".tiff"; unlink $file.".ps"; $s++;
print OU "> Fine\n" if($debug); close OU; exit(0); Analizzando per grandi linee questo script possiamo osservare come consenta di: convertire il file da postscript a pdf utilizzando l utility standard ps2pdf (verificarne la presenza sul sistema server) salvarlo in una directory il cui nome è il numero di fax mittente e dentro la quale viene depositato il fax Inviare una mail con il link al fax in pdf all utente amministratore del sistema specificato nella direttiva MAILTO Il tutto può poi essere organizzato con un semplice programmino che consenta l ordinamento e lettura dei fax direttamente via web, la cui realizzazione non verrà comunque trattata in questo articolo. Per chi invece preferisse ricevere direttamente per email in allegato il fax in formato pdf è possibile utilizzare questa versione dello script new_fax: #!/usr/bin/perl -w # $base="/var/spool/fax/archivio/"; $MAILTO="paolo\@netlink.it"; $from="fax Server <fax\@netlink.it>"; $nopt="-s"; $sopt=""; my $hangup_code = shift; my $sender_id = shift; my $number_pages = shift; print "code:$hangup_code\n"; print "sender:$sender_id\n"; print "pagine:$number_pages\n"; $t=0; foreach $file (@ARGV) $pag[$t]=$file; @partif=split /\//,$file; $ida=$partif[int(@partif)-1]; ($id,$num)=split /\-/,$ida; ($f,$r,$k)=split //,$id; print $file," = $r:$f:$k\n"; system "fax2tiff $file $nopt -M -4 -o ".$file.".tiff" if ($r eq 'n'); system "fax2tiff $file $sopt -M -4 -o ".$file.".tiff" if ($r ne 'n'); system "tiff2ps ".$file.".tiff -h 11.7 -w 8.3 -O $file.ps"; $t++; @parti=split /\//,$pag[0]; $ida=$parti[int(@parti)-1]; ($id,$num)=split /\-/,$ida; $s=0; while($s<$t) $file=$pag[$s]; system "cat $file.ps >>$$.ps"; $s++; # # #system "lpr -b -P stampante $$.ps" system "ps2pdf $$.ps $$.pdf"; $sender_id=~s/\s//g; if ($sender_id eq '') $sender_id='non_identificato';
system "metasend -b -F \"$from\" -f $$.pdf -m application/pdf -s \"Ricevuto fax da $sender_id\" -S 4000000 -t $MAILTO"; $filtro='\s,\/,\\\\,\-,\+,\*,\$,\%,\(,\),\='; foreach $fl (split /\,/,$filtro) print "Filtro: (",$fl,")\n"; $sender_id=~s/$fl//g; if (not(-e "$base$sender_id")) system "mkdir $base$sender_id"; system "cat $$.pdf >$base$sender_id/$id.pdf"; unlink "$$.ps"; unlink "$$.pdf"; $s=0; while($s<$t) $file=$pag[$s]; # unlink $file; unlink $file.".tiff"; unlink $file.".ps"; $s++; exit(0); Doc: fax_linux.pdf Dott. Paolo PAVAN [Netlink Sas] pavan@netlink.it Data: Settembre 2002 Note finali! Il presente documento è a semplice scopo divulgativo! L autore non si assume la responsabilità di eventuali danni diretti o indiretti derivanti dall'uso dei programmi, o dall applicazione delle configurazioni menzionanate nel seguente articolo! L uso od il riutilizzo del presente articolo è liberamente consentito per scopi didattici o informativi previa citazione della fonte.! Gli script presentati nel documento sono stati riadattati da Massimo Nuvoli massimo@nuvoli.to.it il cui contributo si è rivelato indispensabile.