procmailex - przykłady plików rc procmaila przykłady $HOME/.procmailrc Opisu formatu pliku rc znajduje się w procmailrc(5). Technika punktów ważonych jest opisana szczegółowo na stronie procmailsc(5). Ta strona podręcznika pokazuje kilka przykładowych reguł. Przykłady kompletnych plików rc znajdują się w sekcji UWAGI podręcznika procmail(1); można też zajrzeć do przykładowych plików rc w katalogu /usr/share/doc/procmail/examples. Sortuje pocztę przychodzącą z listy dyskusyjnej scuba-dive do folderu pocztowego scubafile (używa lokalnego pliku blokującego scubafile.lock). 3 :0: * ^TOscuba scubafile Forwarduje pocztę o kompilatorach od petera do williama (i zachowuje kopię lokalnie w pliku petcompil). 10 :0 * ^From.*peter * ^Subject:.*compilers { :0 c ! william@somewhere.edu :0 petcompil } Równoważne rozwiązanie, które robi to samo: 7 :0 c * ^From.*peter * ^Subject:.*compilers ! william@somewhere.edu :0 A petcompil Równoważne, lecz trochę wolniejsze rozwiązanie, robiące to samo: 9 :0 c * ^From.*peter * ^Subject:.*compilers ! william@somewhere.edu :0 * ^From.*peter * ^Subject:.*compilers petcompil Nowicjusze w temacie procmaila, planujący trochę z nim poeksperymentować, powinni zapewnić sobie jakiś rodzaj sieci bezpieczeństwa. Wstawienie następujących dwóch reguł przed wszystkimi innymi regułami, zapewni, że ostatnie 32 wiadomości będą chronione. Aby działało to zgodnie z oczekiwaniami, należy przed dodaniem tych dwóch reguł, w katalogu $MAILDIR utworzyć katalog o nazwie "backup". 5 :0 c backup :0 ic | cd backup && rm -f dummy `ls -t msg.* | sed -e 1,32d` Jeśli system nie generuje początkowych linii "From " lub generuje je w nieprawidłowy sposób, to można to naprawić, wywołując procmail z opcją -f-. Innym sposobem naprawienia tego problemu jest wstawienie następujących dwóch reguł powyżej wszystkich innych reguł pliku rc. Będą one filtrować nagłówek dowolnego listu za pomocą formail(1), który obetnie wszelkie początkowe "From " i automatycznie je odtworzy. 2 :0 fhw | formail -I "From " -a "From " Dodaje nagłówki wszystkich wiadomości, które nie przyszły od postmastera, do prywatnej kolekcji nagłówków (dla statystyk lub debuggowania poczty); używa pliku blokującego "headc.lock". Aby zapewnić, że plik blokujący nie zostanie usunięty przed zakończeniem potoku, trzeba podać opcję "w"; w przeciwnym wypadku plik blokujący zostałby usunięty w momencie przyjęcia poczty przez potok. 3 :0 hwc: * !^FROM_MAILER | uncompress headc.Z; cat >>headc; compress headc Lub aby użyć efektywniejszego gzip-a zamiast compress-a: 3 :0 hwc: * !^FROM_MAILER | gzip >>headc.gz Forwarduje wszystkie wiadomości krótsze niż 1000 bajtów na podany adres domowy (w tej regule nie jest potrzebny plik blokujący). 3 :0 * < 1000 ! myname@home Dzieli pochodzącą z listy dyskusyjnej surfing kolekcję wiadomości (ang. digest) na pojedyncze wiadomości i zachowuje je w pliku surfing, używając lokalnego pliku blokującego surfing.lock. 3 :0: * ^Subject:.*surfing.*Digest | formail +1 -ds >>surfing Zachowuje w pliku postm wszystkie e-maile pochodzące od postmastera lub mailer-deamona. Użyje pliku postm.lock jako lokalnego pliku blokującego. 3 :0: * ^FROM_MAILER postm Prosta reguła auto-odpowiadająca. Upewnia się, że nie odpowiada na pocztę od jakiegoś demona (np. odbita poczta lub poczta z list dyskusyjnych), ani na listy pochodzące od Ciebie samego. Bez tych zabezpieczeń mogłaby się zdarzyć katastrofa. Aby reguła odpowiadała na pocztę przychodzącą, powinno się ją wstawić przed wszystkie inne reguły pliku rc. Radzi się jednak wstawiać ją za wszelkimi regułami, które obsługują pocztę pochodzącą z list dyskusyjnych; zazwyczaj nie jest dobrym pomysłem generowanie automatycznych odpowiedzi na pocztę z list dyskusyjnych (tak, regexp !^FROM_DAEMON powinien je wyłapać, jednak jeśli lista dyskusyjna nie pracuje zgodnie z przyjętymi konwencjami, to może to być niewystarczające). 6 :0 h c * !^FROM_DAEMON * !^X-Loop: twój@własny.adres.pocztowy | (formail -r -A"Precedence: junk" \ -A"X-Loop: twój@własny.adres.pocztowy" ; \ echo "Poczta odebrana.") | $SENDMAIL -t Bardziej skomplikowana reguła auto-odpowiadająca, która implementuje funkcjonalność znanego programu vacation(1). Reguła ta jest oparta na tych samych zasadach, co poprzednia (zapobieganie odbijania maili od demonów). Dodatkowo utrzymuje bazę danych vacation, wyciągając nazwę nadawcy i wstawiając ją do pliku vacation.cache, o ile była to nowa nazwa (plik vacation.cache jest obsługiwany przez formail(1), który będzie się upewniał, że zawiera tylko najnowsze nazwiska; rozmiar pliku jest ograniczony do 8192 bajtów). Jeśli nazwisko było nowe, wysłana zostanie automatycznie wygenerowana odpowiedź. Jak można zauważyć następująca reguła zawiera komentarze pomiędzy warunkami. Jest to dozwolone. Jednakże nie można wpisywać komentarzy w linii zawierającej warunek. 18 SHELL=/bin/sh # dla innych powłok trzeba to poprawić :0 Whc: vacation.lock # Szybkie sprawdzenie, czy poczta jest adresowana do nas * $^To:.*\<$\LOGNAME\> # Nie odpowiadaj na maile od usług lub z list pocztowych * !^FROM_DAEMON # Pętle pocztowe to zło * !^X-Loop: your@own.mail.address | formail -rD 8192 vacation.cache :0 ehc # jeśli nazwiska nie było w cache | (formail -rA"Precedence: junk" \ -A"X-Loop: twój@własny.adres.pocztowy" ; \ echo "Odebrałem Twój list,"; \ echo "lecz nie wrócę do poniedziałku."; \ echo "-- "; cat $HOME/.signature \ ) | $SENDMAIL -oi -t Zachowuje wszelkie wiadomości dotyczące TeX-a w oddzielnych plikach o unikatowych nazwach w katalogu o nazwie texmail (katalog musi istnieć); nie ma potrzeby używać w tym wypadku plików blokujących, więc ich nie używamy. 3 :0 * (^TO|^Subject:.*)TeX[^t] texmail To samo, co powyżej, lecz teraz zapisuje listy w plikach numerowanych (folder pocztowy MH). 3 :0 * (^TO|^Subject:.*)TeX[^t] texmail/. Można także zapisać list w kilku folderach naraz. Następująca reguła dostarczy pocztę do dwóch folderów MH i jednego folderu katalogowego. Jest to w rzeczywistości tylko jeden plik z dwoma dodatkowymi dowiązaniami twardymi (hardlinks). 3 :0 * (^TO|^Subject:.*)TeX[^t] texmail/. wordprocessing dtp/. Zachowuje wszystkie listy o spotkaniach (meetings) w folderze znajdującym się w katalogu, którego nazwa się zmienia co miesiąc. Np. jeśli był styczeń 1994, folder miałby nazwę "94-01/meeting", a lokalny plik blokujący nazywałby się "94-01/meeting.lock". 3 :0: * meeting `date +%y-%m`/meeting To samo, co wyżej, lecz jeśliby katalog "94-01" nie istniał, toby został automatycznie utworzony: 9 MONTHFOLDER=`date +%y-%m` :0 Wic * ? test ! -d $MONTHFOLDER | mkdir $MONTHFOLDER :0: * meeting ${MONTHFOLDER}/meeting To samo, co powyżej, lecz z użyciem innych środków: 6 MONTHFOLDER=`date +%y-%m` DUMMY=`test -d $MONTHFOLDER || mkdir $MONTHFOLDER` :0: * meeting ${MONTHFOLDER}/meeting Jeśli jest się zapisanym do kilku list dyskusyjnych, a ludzie wysyłają te same maile na niektóre z nich, to może się zdarzyć, że otrzyma się zduplikowane listy (po jednym z każdej listy). Następująca reguła eliminuje powtórzone maile. Mówi formailowi, by trzymał 8-kilobajtowy plik bufora, w którym będzie zapisywał Message-ID ostatnio odbieranych listów. Ponieważ elementy te muszą być unikatowe dla każdego nowego listu, to są idealnym rozwiązaniem na duplikaty. Wystarczy wstawić następującą regułę na początek pliku rc i gotowe. 2 :0 Wh: msgid.lock | formail -D 8192 msgid.cache Uwaga: jeśli wystąpią problemy z dostarczaniem poczty w regułach występujących po tej regule i procmail spróbuje wrzucić mail z powrotem do kolejki, to w czasie następnego uruchomienia kolejki mail zostanie uznany za duplikat i wyrzucony. Ktoś, kto nie ma zbyt dużych umiejętności w pisaniu skryptów, może spróbować użyć następującej reguły, która zapisze duplikaty w osobnym folderze zamiast wyrzucać je całkowicie. Folder ten można od czasu do czasu przeglądać i opróżniać. 5 :0 Whc: msgid.lock | formail -D 8192 msgid.cache :0 a: duplicates Procmail może dostarczać pocztę bezpośrednio do folderów MH, ale nie aktualizuje pliku sekwencji, którym zarządza prawdziwe MH, zawierającego informacje o nieprzeczytanej poczcie. Aby procmail aktualizował ten plik także, należy użyć reguły podobnej do poniższej. Reguła ta zapisze wszystko, co zawiera w treści maila słowo "spam" do folderu MH zwanego spamfold. Proszę zwrócić uwagę na lokalny plik blokujący, który jest potrzebny, ponieważ programy MH nie blokują pliku sekwencji. Asynchroniczne uruchomienia programów MH, które zmieniają plik sekwencji, mogą spowodować jego uszkodzenie. Niestety plik blokady nie rozwiązuje całkowicie problemu, ponieważ rcvstore(1) może zostać uruchomiony w czasie działania poleceń "show" lub "mark" lub jakiegoś innego programu MH. Problem ma zostać rozwiązany w przyszłych wersjach MH, zanim to jednak nastąpi należy się liczyć z ryzykiem uszkodzenia plików sekwencji. 3 :0 :spamfold/$LOCKEXT * B ?? spam | rcvstore +spamfold Podczas bezpośredniego dostarczania do folderów emacsa (np. folderów pocztowych obsługiwanych przez dowolny pocztowy pakiet emacsowy, np. RMAIL czy VM), powininno się używać kompatybilnych z emacsem plików blokujących. Mailerom emacsowym brakuje piątej klepki pod tym względem, denerwują się bardzo, jeśli ktoś dostarcza pocztę do folderów, które znajdują się już w ich buforach wewnętrznych. Następująca reguła zakłada, że $HOME jest równy /home/john. 5 MAILDIR=Mail :0:/usr/local/lib/emacs/lock/!home!john!Mail!mailbox * ^Subject:.*cokolwiek mailbox Inaczej, można kazać procmailowi dostarczać pocztę do swoich własnych mailboxów, a następnie periodycznie opróżniać je i kopiować do plików emacsowych przy użyciu movemail(1). Movemail używa lokalnych plików blokujących mailbox.lock dla danego mailboxa. Jest to preferowany tryb współpracy emacsowych mailerów z procmailem. Aby wyciągnąć określone nagłówki z listu i wstawić je do zmiennych środowiskowych, można użyć dowolnej z następujących konstrukcji: 5 SUBJECT=`formail -xSubject:` # pole regularne FROM=`formail -rt -xTo:` # przypadek specjalny :0 h # metoda alternatywna KEYWORDS=| formail -xKeywords: Jeśli w pliku .procmailrc używane są pliki tymczasowe, to aby upewnić się, że zostaną one usunięte zaraz przed zakończeniem pracy procmaila, można użyć linijek podobnych do tych: 2 TEMPORARY=$HOME/tmp/pmail.$$ TRAP="/bin/rm -f $TEMPORARY" Słowo kluczowe TRAP może być także użyte do zmiany kodu wyjścia procmaila. Np. aby procmail zakończył pracę z kodem wyjścia "1" zamiast standardowego kodu, można użyć: 3 EXITCODE="" TRAP="exit 1;" # Kończący średnik jest istotny # gdyż exit nie jest samodzielnym programem Albo też, jeśli kod wyjścia nie musi zależeć od programów uruchamianych z TRAP, można użyć zwykłego: 1 EXITCODE=1 Następująca reguła drukuje każdy nadchodzący list, który wygląda jak plik postscriptowy. 3 :0 Bb * ^^%! | lpr Następująca reguła robi to samo, lecz jest trochę bardziej selektywna. Drukuje tylko te pliki postscriptowe, które pochodzą od serwera drukarki. Pierwszy warunek dopasowuje tylko, jeśli zostanie znaleziony w nagłówku. Następny dopasowuje tylko na początku ciała wiadomości. 4 :0 b * ^From[ :].*print-server * B ?? ^^%! | lpr To samo, co powyżej, lecz z użyciem innych środków: 7 :0 * ^From[ :].*print-server { :0 B b * ^^%! | lpr } Podobnie: 4 :0 HB b * ^^(.+$)*From[ :].*print-server * ^^(.+$)*^%! | lpr Załóżmy, że mamy dwa konta i że oba są używane regularnie, lecz znajdują się w całkowicie różnych miejscach (tj. można czytać pocztę tylko z jednego z dwóch kont). Chcielibyśmy przekazywać pocztę przybywającą na konto pierwsze do konta drugiego i odwrotnie. Pierwszą rzeczą, która przychodzi na myśl jest użycie na obydwu komputerach plików .forward, lecz to nie zadziała, gdyż utworzy się w ten sposób pętlę pocztową. Można uniknąć pętli przez wstawienie następującej reguły na początku wszystkich innych reguł w plikach $HOME/.procmailrc obydwu komputerach. Jeśli dodane zostanie dokładnie to samo pole "X-Loop:" na obydwu komputerach, to poczta może już być bezpiecznie przekazywana z jednego z tych kont na drugie. 4 :0 c * !^X-Loop: twojlogin@twoj.adres.pocztowy | formail -A "X-Loop: twojlogin@twoj.adres.pocztowy" | \ $SENDMAIL -oi twojlogin@drugie.konto Jeśli ktoś prześle pocztę ze słowem "retrieve" w temacie, to następująca reguła automatycznie odeśle z powrotem zawartość pliku info_file. Jak we wszystkich regułach, należy uważać na pętle pocztowe. 6 :0 * !^From +TWOJ_USERNAME * !^Subject:.*Re: * !^FROM_DAEMON * ^Subject:.*retrieve | (formail -r ; cat info_file) | $SENDMAIL -oi -t A teraz przykład bardzo prostego serwera plików dostępnego przez pocztę. Dla bardziej wymagających aplikacji, sugeruję zapoznanie się z programem SmartList (dostępnym w tym samym miejscu, co dystrybucja procmaila). Ten serwer plików odsyła najwyżej jeden plik na żądanie, ignoruje ciało nadchodzących listów, a linia tematu Subject: musi wyglądać jak "Subject: send file plik_którego_chcesz" (spacje są istotne), nie zwraca plików, które mają nazwy rozpoczynające się od kropki i nie umożliwia odbioru plików spoza drzewa katalogów serwera plików (dostosowując ten przykład do własnych potrzeb, prosimy pamiętać o tym, by nieumyślnie nie zdjąć ostatniego z wymienionych ograniczeń). 18 :0 * ^Subject: send file [0-9a-z] * !^X-Loop: twojlogin@twoj.adres.pocztowy * !^Subject:.*Re: * !^FROM_DAEMON * !^Subject: send file .*[/.]\. { MAILDIR=$HOME/fileserver # zmień katalog do katalogu serwera plików :0 fhw # odwróć nagłówek listu i wyciągnij nazwę * ^Subject: send file \/[^ ]* | formail -rA "X-Loop: twojlogin@twoj.adres.pocztowy" FILE="$MATCH" # żądany plik :0 ah | cat - ./$FILE 2>&1 | $SENDMAIL -oi -t } Następujący przykład zamienia wstępnie wszystkie przychodzące listy w czystym tekście, kodowane w formatach MIME na ładniejszy format 8-bitowy, który może być używany i wyświetlany w prostszy sposób przez większość programów. Program mimencode(1) jest częścią pakietu metamail Nathaniela Borensteina. 17 :0 * ^Content-Type: *text/plain { :0 fbw * ^Content-Transfer-Encoding: *quoted-printable | mimencode -u -q :0 Afhw | formail -I "Content-Transfer-Encoding: 8bit" :0 fbw * ^Content-Transfer-Encoding: *base64 | mimencode -u -b :0 Afhw | formail -I "Content-Transfer-Encoding: 8bit" } Następujący przykład jest raczej egzotyczny, lecz służy tylko ilustracji właściwości. Załóżmy, że masz w swoim katalogu domowym plik o nazwie ".pilne", a osoba wymieniona w tym pliku jest nadawcą nadchodzącego listu i chciałbyś, by ten list był zachowany w skrzynce "$MAILDIR/pilne" zamiast w dowolnym z normalnych folderów pocztowych. Można wówczas zrobić tak (uwaga: długość pliku $HOME/.pilne powinna być mniejsza niż $LINEBUF, jeśli to konieczne, należy zwiększyć wartość LINEBUF): 5 URGMATCH=`cat $HOME/.pilne` :0 B: * $^From.*${URGMATCH} pilne Całkowicie innym zastosowaniem procmaila byłoby warunkowe dołączanie filtrów do niektórych (wychodzących) tekstów lub listów. Typowym przykładem byłoby filtrowanie, w którym używane byłyby potoki dla wszystkich wychodzących e-maili, aby ustawić kodowanie MIME tylko wtedy, gdy to konieczne. W takim przypadku można uruchomić procmaila wewnątrz potoku na przykład w taki sposób: 1 cat newtext | procmail ./mimeconvert | mail chris@where.ever Plik rc mimeconvert powinien zawierać coś w rodzaju (=0x80= i =0xff= powinny być zastąpione prawdziwymi znakami 8-bitowymi): 10 DEFAULT=| # potok na stdout zamiast # dostarczania pocztę jak zwykle :0 Bfbw * [=0x80=-=0xff=] | mimencode -q :0 Afhw | formail -I 'MIME-Version: 1.0' \ -I 'Content-Type: text/plain; charset=ISO-8859-1' \ -I 'Content-Transfer-Encoding: quoted-printable' procmail(1), procmailrc(5), procmailsc(5), sh(1), csh(1), mail(1), mailx(1), uucp(1), aliases(5), sendmail(8), egrep(1), grep(1), biff(1), comsat(8), mimencode(1), lockfile(1), formail(1) Stephen R. van den Berg <srb@cuci.nl> Philip A. Guenther <guenther@sendmail.com> Autorami polskiego tłumaczenia niniejszej strony podręcznika man są: Przemek Borys (PTM) <pborys@dione.ids.pl> i Robert Luberda <robert@debian.org>. Polskie tłumaczenie jest częścią projektu manpages-pl; uwagi, pomoc, zgłaszanie błędów na stronie http://sourceforge.net/projects/manpages-pl/. Jest zgodne z wersją 3.22 oryginału.